<?xml version="1.0" encoding="UTF-8"  standalone="yes" ?>
<rss version="2.0">
	<channel>
		<title>社群: 艾鍗學院 Blog - 文件區(Embedded LInux 專欄)</title>
		<description>台灣數位學習數位教學平台 RSS feed provider</description>
		<language>zh-tw</language>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doclist&amp;folderID=1224</link>
	<item>
		<title>使用Tortoise SVN</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=12934</link>
		<description>使用使用Tortoise SVN&amp;nbsp;Client 教學https://farm6.staticflickr.com/5615/15558938047_99d01b33dd_k.jpg       </description>
		<pubDate>Sun, 09 Nov 2014 11:13:24 +0800</pubDate>
	</item>
	<item>
		<title>NetLink Socket 範例程式</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=11819</link>
		<description>&amp;nbsp;附件為NetLink Socket 範例程式..   </description>
		<pubDate>Sun, 11 May 2014 08:51:06 +0800</pubDate>
	</item>
	<item>
		<title>LIRC GPIO driver</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=10447</link>
		<description>Raspberry Pi lirc_rpi - (IR Remote control) LIRC GPIO driverhttp://aron.ws/projects/lirc_rpi/ </description>
		<pubDate>Tue, 18 Feb 2014 20:06:58 +0800</pubDate>
	</item>
	<item>
		<title>Linux IR 解碼</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=10376</link>
		<description>每一Bit 的傳送,都是38KHZ的載波頻率在發送.NEC Infrared Protocol&amp;nbsp;A 9ms leading pulse burst (16 times the pulse burst length used for a logical data bit)A 4.5ms spaceThe 8-bit address for the receiving deviceThe 8-bit logical inverse of the addressThe 8-bit commandThe 8-bit logical inverse of the commandFinal 562.5µs pulse burst to show end of message transmission.Logical &#039;0&#039; – a 562.5µs pulse burst followed by a 562.5µs space, with a total transmit time of 1.125msLogical &#039;1&#039; – a 562.5µs pulse burst followed by a 1.6875ms space, with a total transmit time of 2.25 &amp;nbsp; &amp;nbsp;Pulse 係由很多 on/off 交替的訊號所組成:Carrier frequency = 38kHzduty factor = 1/3period = 26.5us16 bits for the address (address + inverse) require&amp;nbsp;27ms to transmit time&amp;nbsp;.and the 16 bits for the command (command + inverse) also&amp;nbsp;require&amp;nbsp;27ms to transmit time.&amp;nbsp;&amp;nbsp;because (address + address inverse) or (command+command inverse) will always contain 8 &#039;0&#039;s &amp;nbsp;and 8 &#039;1&#039;s &amp;nbsp; &amp;nbsp;so&amp;nbsp;(8 * 1.125ms) + (8 * 2.25ms) == 27 ms .&amp;nbsp;according to this total time required to transmit the frame is&amp;nbsp;(9ms +4.5ms +27ms+27ms) = 67.5 ms.&amp;nbsp;&amp;nbsp;If the key on the remote controller is kept depressed, a repeat code will be issued, typically around 40ms after the pulse burst that signified the end of the message. A repeat code will continue to be sent out at 108ms intervals, until the key is finally released. The repeat code consists of the following, in order:A 9ms leading pulse burstA 2.25ms spaceA 562.5µs pulse burst to mark the end of the space (and hence end of the transmitted repeat code).the figures give blow show the timing of repeat codesif user keeps the key depressed the repeat codes keep coming==========static irqreturn_t cir_irq_handler (int irq, void *dev_id, struct pt_regs *regs)
{
    struct timeval tv;
    long deltv;
    int data;
    struct cir_device_data *dev;
    
    dev = (struct cir_device_data *)dev_id;
    
    /* get current time */
    do_gettimeofday(&amp;amp;tv);
    
    if(dev-&amp;gt;ir_state == IR_STATE_0) {
        dev-&amp;gt;ir_state = IR_STATE_1;
        /* Initializate ir variable */
        dev-&amp;gt;ir_count = 0; 
        dev-&amp;gt;complete_bits = 0;
        
        /* Configure to generate an interrupt on rising edge
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* Wait 9ms pre-pulse.   
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/
        set_irq_type(gpio_to_irq(CIR_GPIO), IRQT_RISING);
    } else {
        deltv = tv.tv_sec - dev-&amp;gt;lasttv.tv_sec;
        
        /* calc time since last interrupt in microseconds */
        data = (int) (deltv*1000000 + tv.tv_usec - dev-&amp;gt;lasttv.tv_usec);
        decode_process(dev, data);
    }
    
    /* restore time */
    dev-&amp;gt;lasttv = tv;
    
    return IRQ_HANDLED;
}static int check_bit(int interval)
{
    int bit = 0;

    /* if interval is 1.12ms(+-20%) then bit 0 */
    if(interval &amp;gt; 896 &amp;amp;&amp;amp; interval &amp;lt; 1344) 
        bit = 0;
    /* if interval is 2.25ms(+-20%) then bit 1 */
    else if(interval &amp;gt; 1800 &amp;amp;&amp;amp; interval &amp;lt; 2700)
        bit = 1;
    else
    /* invalid data bit */    
        bit = -1;  
    
    return bit;
}

static void decode_process(struct cir_device_data *dev, int interval)
{
    int bitvalue = 0;
    
    switch(dev-&amp;gt;ir_state){
        case IR_STATE_1:
            /* Configure to generate an interrupt on falling edge
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* decision 9ms pre-pulse, within a +-20% range of the nominal value
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* 9000 - (9000*0.2) = 7200, 9000+(9000*0.2) = 9900
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/
            set_irq_type(gpio_to_irq(CIR_GPIO), IRQT_FALLING);
            if(interval &amp;gt; 7200 &amp;amp;&amp;amp; interval &amp;lt; 10800) 
                dev-&amp;gt;ir_state = IR_STATE_2; // pre-pulse detected.
            else 
                dev-&amp;gt;ir_state = IR_STATE_0; // exit with error, return state_0
            break;
        case IR_STATE_2:
           /* decision long interval(4.5ms) or short interval (2.25ms)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* long interval is normal message, short interval is repetition code.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* 4500 - (4500*0.2) = 3600, 4500 + (4500*0.2) = 5400
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* 2250 - (2250*0.2) = 1800, 2250 + (2250*0.2) = 2700
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/
            if(interval &amp;gt; 3600 &amp;amp;&amp;amp; interval &amp;lt; 5400) {  
                dev-&amp;gt;ir_state = IR_STATE_3; 
            } else if(interval &amp;gt; 1800 &amp;amp;&amp;amp; interval &amp;lt; 2700) {
                /* driver not supported repetition. 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* Return state_0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/
                dev-&amp;gt;ir_state = IR_STATE_0; //repeat state.
            } else {
                dev-&amp;gt;ir_state = IR_STATE_0;     // exit with error, return state_0
                printk(KERN_DEBUG &quot;CIR:exit with error!\n&quot;);
            }
            break;
        case IR_STATE_3:
           /* 32 bits entire message receiving
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/
             bitvalue = check_bit(interval);
             if(bitvalue &amp;lt; 0) {
                 /* invalid data bit */ 
                 dev-&amp;gt;ir_state = IR_STATE_0;
             } else {
                 dev-&amp;gt;complete_bits &amp;lt;&amp;lt;= 1;
                 dev-&amp;gt;complete_bits |= bitvalue;
                 dev-&amp;gt;ir_state = IR_STATE_3;
                 dev-&amp;gt;ir_count++;
                 
                 if(dev-&amp;gt;ir_count &amp;gt;= CIR_DATA_BITS) {
                     /* receiving complete */ 
                     dev-&amp;gt;ir_state = IR_STATE_0;
                     /* store to buffer */
                     dev-&amp;gt;buff[dev-&amp;gt;head] = dev-&amp;gt;complete_bits;
                    dev-&amp;gt;head = (dev-&amp;gt;head + 1) % CIR_BUFFER_SIZE;
                     wake_up_interruptible(&amp;amp;dev-&amp;gt;waitq);
                 } 
             }
            break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;default:
            break;
    }
}參考資料:&amp;nbsp;[1]&amp;nbsp;http://personlin118.pixnet.net/blog/post/69022-ir-driver-(kernel-2.6.18)[2]&amp;nbsp;http://coopermaa2nd.blogspot.tw/2010/01/nec-ir-protocol.html                         </description>
		<pubDate>Mon, 10 Feb 2014 23:30:49 +0800</pubDate>
	</item>
	<item>
		<title>BeagleBoard系統安裝</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=10295</link>
		<description>&amp;nbsp;BeagleBoard系統安裝   </description>
		<pubDate>Mon, 11 Nov 2013 15:03:53 +0800</pubDate>
	</item>
	<item>
		<title>blocking and nonblocking input</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=10081</link>
		<description></description>
		<pubDate>Sat, 06 Jul 2013 01:35:29 +0800</pubDate>
	</item>
	<item>
		<title>[嵌入式Linux] Flash 要如何規劃?</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=9886</link>
		<description>&amp;nbsp;Flash 要如何規劃? 有何注意事項&amp;nbsp;&amp;nbsp;&amp;nbsp;Flash 規劃成不同Partition, 每個Partition 的起始位置, ;必須規劃在 Erase Boundary 上&amp;nbsp;且 size 最好是&amp;nbsp;Erase size的整數倍.&amp;nbsp;&amp;nbsp;&amp;nbsp;Erase 大小如何知道; ,請查看你所使用的Flash Spec., 例如:&amp;nbsp;------------------------------------------------------------------     </description>
		<pubDate>Sat, 27 Apr 2013 12:14:10 +0800</pubDate>
	</item>
	<item>
		<title>[嵌入式Linux] SPI的CPOL和CPHA意義</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=9858</link>
		<description> 【SPI的CPOL和CPHA】CPOL : 決定SCLK idle 的state, ,即平時是在low還是highCPHA: 決定取樣點是在第一個edge,還是第二個edge 因此共有四種資料擷取的模式 (Strobe), 要用那一種, 看你的SPI Device 本身而定 反正SPI Master 都可以配合去設定Mode 0CPOL=0, CPHA=0; active highMode 1CPOL=0, CPHA=1 ;active lowMode 2CPOL=1, CPHA=0 ;active lowMode 3CPOL=1, CPHA=1;active highfrom Richman&#039;s Linux 驅動程式講義      </description>
		<pubDate>Sat, 20 Apr 2013 10:48:16 +0800</pubDate>
	</item>
	<item>
		<title>[嵌入式Linux] 關於  reqest_mem_region</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=9857</link>
		<description>&amp;nbsp;reqest_mem_region() --&amp;gt; 向kernel 請求某一塊記憶空間(Physical&amp;nbsp;address), 避免別人也搶到這一塊, 但在SoC 沒有太大意義,&amp;nbsp;因為根本不會有人去搶, 每一個元件都是獨立的區域cat /proc/iomem --&amp;gt; 得知所有Driver 所佔區域&amp;nbsp;&amp;nbsp;&amp;nbsp;reqest_mem_region()&amp;nbsp;---&amp;gt; Physical address&amp;nbsp; 接在還要進行 &amp;nbsp;ioremap() ,取得kernel 下的 Virtual address&amp;nbsp; 之後,你的driver 程式,才可以用 readl(), writel() 去讀寫       </description>
		<pubDate>Sat, 20 Apr 2013 10:17:16 +0800</pubDate>
	</item>
	<item>
		<title>TCP TIME_WAIT的釋義</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=9668</link>
		<description>TCP TIME_WAIT的釋義在實務中, 許多情況下, 可能是Server Socket出現了問題, 勢必採取關閉原有的Sever Socket, 再隨即重新啟動新建的Server Socket. 但此刻會發生一個問題, 就是相隔時間過短, 在新建的Sever Socket進行bind()的程序時, 系統會出現一錯誤訊息&quot;the address already in use&quot;.照一般想法, Server Socket都已Close, 理應已釋放出該IP Address之資源, 怎會出現這個令人莫名的訊息呢??關鍵在於TCP建立於多次的握手協定的基礎上, 以達到保證訊息傳遞的完整性.由於TPC是全雙工傳輸, 換言之, 雙向的傳輸必須單獨進行關閉, 原則上主動請求關閉的一方A, 藉由發送FIN來請求終止這個方向的連接. 被動關閉的一方B, 收到FIN表示A--&amp;gt;B的方向已無資料進行傳送, 此時B--&amp;gt;A仍是可以進行資料傳送, 待B執行被動關閉.簡言之, A欲進行關閉傳輸時, 必須通知B並確認, 而B欲進行關閉傳輸時, 也必須通知A並確認.關閉連線:(如上圖所示)(1) 當處於ESTABLISHED狀態時, TCP B欲主動關閉連線, 發送FIN至TCP A, 進入到FIN-WAIT-1狀態, 等待TCP A回應ACK, 表示等待確認TCP A得知TCP B要關閉連線(2) 當TCP A收到TCP B的FIN時, 立即回應ACK給TCP B, 進入到CLOSE-WAIT狀態, 表示須等到應用程序沒有任何資料要傳送給TCP B, TCP A才決定關閉連線(3) TCP B收到TCP A回應的ACK, 表示確認TCP A得知TCP B要關閉連線, 此刻等待TCP A發送FIN(4) TCP A決定關閉連線, 發送FIN至TCP B, 進入到LAST-ACK狀態, 等待TCP B回應ACK, 表示等待確認TCP B得知TCP A要關閉連線(5) TCP B收到TCP A的FIN後, 隨即回應ACK, 進入TIME_WAIT狀態, 表示TCP B得知TCP A要關閉連線, 且等待2MSL時間, 以防TCP A再次發送FIN(6) TCP A收到TCP B回應的ACK後, 進入CLOSED狀態, 表示TCP A已確認TCP B已得知它要關閉連線, 才進行關閉連線(7) TCP B等待2MSL時間, 才進入CLOSED狀態, 關閉連線, 並自連線表中移除在上述的第(5),(7)點, 此刻TIME-WAIT的用意在於, 雖TCP B已確認TCP A要關閉連線, 且回應了ACK給TCP A, 但不保證TCP A會收到ACK, 一旦ACK遺漏, TCP A會再次發送FIN給TCP B, 再次進行確認, 所以TCP B須進入TIME-WAIT狀態, 等待2MSL時間, 預防TCP A會再次發送FIN, 進行連線關閉的確認different states of a TCP connection:LISTEN&amp;nbsp;: awaiting a connection request from client (監聽客戶端的連線請求)SYN-SENT&amp;nbsp;: a SYN has been sent to server, and client is awaiting the ACK of SYN (發送SYN, 並等待服務端回應SYN的ACK)SYN-RECEIVED&amp;nbsp;: a SYN has been received from client, a SYN with ACK has been sent to client, and server is awaiting the ACK of SYN (接收客戶端的SYN, 另傳送SYN+ACK(SYN)給客戶端, 並等待客戶端回應SYN的ACK)ESTABLISHED&amp;nbsp;: the three-way handshake has been completed, and established the connection (完成握手協定, 並建立連線)FIN-WAIT-1&amp;nbsp;: the local AP has issued a close. active TCP has sent a FIN to passive TCP, and is awaiting an ACK of FIN (主動端發出FIN至被動端, 並等待被動端回應FIN的ACK)FIN-WAIT-2&amp;nbsp;: a previous FIN has been sent to passiveTCP, and received an ACK of FIN from passive TCP. active TCP is awaiting a FIN from the passive TCP (成功接收到先前傳送至被動端FIN的ACK, 此刻等待被動端傳送FIN)CLOSE-WAIT&amp;nbsp;: passive TCP has received a FIN from active TCP, and has sent an ACK of FIN to active TCP. passive TCP is awaiting a close request from remote AP before sending a FIN (被動端已接收主動端的FIN, 並傳送FIN的ACK至主動端, 此刻等待AP要求關閉連線)LAST-ACK&amp;nbsp;: previously a FIN has been received from active TCP, and an ACK of FIN has been sent to active TCP, and a FIN has been sent to active TCP. passive TCP is awaiting an ACK of FIN (先前收到主動端的FIN, 且傳送FIN的ACK給主動端, 另被動端傳送FIN給主動端, 此刻被動端等待主動端回應FIN的ACK)TIME-WAIT&amp;nbsp;: FINs have been received and ACK has been sent passive TCP. active TCP is waiting 2MSLs to remove the connection from the connection table (收到被動端的FIN, 並傳送ACK至被動端, 此刻主動端會等待2MSL的時間才將連線關閉)CLOSED&amp;nbsp;: a connection has been removed from the connection table (連線不存在於連線表)資料來源:&amp;nbsp;&amp;nbsp;http://low-understated.blogspot.tw/2009/03/tcp-timewait.html   </description>
		<pubDate>Sat, 02 Feb 2013 15:10:23 +0800</pubDate>
	</item>
	<item>
		<title>test</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=9387</link>
		<description>按一下這裡開小視窗  </description>
		<pubDate>Thu, 15 Nov 2012 11:45:48 +0800</pubDate>
	</item>
	<item>
		<title>如何載入 Ralink Wifi Driver</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=9208</link>
		<description>How-to----------------------載入Kernel Module# insmod rt2870sta.ko&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;rtusb init ---&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;usbcore: registered new interface driver rt2870=== pAd = c607e000, size = 501464 ===&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;-- RTMPAllocTxRxRingMemory, Status=0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;-- RTMPAllocAdapterBlock, Status=0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;usb 1-1: New USB device found, idVendor=148f, idProduct=2870&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;usb 1-1: Product: 802.11 n WLAN&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;usb 1-1: Manufacturer: Ralink ------------------&amp;nbsp;RT2870STA.dat&amp;nbsp;這個檔案在module 載入時,會讀入這個檔案,所以必須要先放在Root filesystem,&amp;nbsp;&amp;nbsp;RT2870STA.dat&amp;nbsp;主要是用來設定wifi連線的參數,如SSID,認證, 加密等,在你要連線某台AP時,必須修改這個檔案以符合你的情況, 另一種方法用iwpriv (,其時就是ioctl 下命令),也可以用進行參數設定, 立即生效若是用&amp;nbsp;RT2870STA.dat, 若更換參數,記得要重對ra0 down再upifconfig ra0 down/up, 因為此時才會Reload 參數Configuration File : RT2870STA.dat---------------------------------------# Copy this file to /etc/Wireless/RT2870STA/RT2870STA.dat# This file is a binary file and will be read on loading rt.o module.## Use &quot;vi RT2870STA.dat&quot; to modify settings according to your need.# # 1.) set NetworkType to &quot;Adhoc&quot; for using Adhoc-mode, otherwise using Infrastructure# 2.) set Channel to &quot;0&quot; for auto-select on Infrastructure mode# 3.) set SSID for connecting to your Accss-point.# 4.) AuthMode can be &quot;WEPAUTO&quot;, &quot;OPEN&quot;, &quot;SHARED&quot;, &quot;WPAPSK&quot;, &quot;WPA2PSK&quot;, &quot;WPANONE&quot;# 5.) EncrypType can be &quot;NONE&quot;, &quot;WEP&quot;, &quot;TKIP&quot;, &quot;AES&quot;# for more information refer to the Readme file.--------------------------------------# ifconfig ra0 up&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;--&amp;gt;RTUSBVenderReset&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;--RTUSBVenderReset&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;Key1Str is Invalid key length(0) or Type(0)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;Key2Str is Invalid key length(0) or Type(0)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;Key3Str is Invalid key length(0) or Type(0)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;Key4Str is Invalid key length(0) or Type(0)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;1. Phy Mode = 5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;2. Phy Mode = 5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;phy mode&amp;gt; Error! The chip does not support 5G band 1!&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;RTMPSetPhyMode: channel is out of range, use first channel=1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;3. Phy Mode = 9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;MCS Set = ff ff 00 00 01&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;==== rt28xx_init, Status=0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;0x1300 = 00064300 ===========# ifconfig ra0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;ra0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Link encap:Ethernet&amp;nbsp; HWaddr 00:0E:2E:DE:28:A7&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UP BROADCAST RUNNING MULTICAST&amp;nbsp; MTU:1500&amp;nbsp; Metric:1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RX packets:372 errors:0 dropped:0 overruns:0 frame:0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TX packets:142 errors:0 dropped:0 overruns:0 carrier:0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; collisions:0 txqueuelen:1000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RX bytes:84814 (82.8 KiB)&amp;nbsp; TX bytes:11360 (11.0 KiB)======================# 進行site survey 動作# iwpriv ra0 get_site_surveyra0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get_site_survey:Ch&amp;nbsp; SSID&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BSSID&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Security&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Siganl(%)W-Mode&amp;nbsp; ExtCH&amp;nbsp; NT1&amp;nbsp;&amp;nbsp; JS_ASUS_RT-N16&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bc:ae:c5:c5:17:ea&amp;nbsp;&amp;nbsp; WPA1PSKWPA2PSK/TKIPAES 60&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11b/g/n NONE&amp;nbsp;&amp;nbsp; In2&amp;nbsp;&amp;nbsp; APTG Wi-Fi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cc:b2:55:03:39:4f&amp;nbsp;&amp;nbsp; NONE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11b/g&amp;nbsp;&amp;nbsp; NONE&amp;nbsp;&amp;nbsp; In2&amp;nbsp;&amp;nbsp; CHT Wi-Fi(HiNet)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cc:b1:55:03:39:4f&amp;nbsp;&amp;nbsp; NONE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11b/g&amp;nbsp;&amp;nbsp; NONE&amp;nbsp;&amp;nbsp; In5&amp;nbsp;&amp;nbsp; JS_Pentens&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bc:ae:c5:c4:d8:f2&amp;nbsp;&amp;nbsp; WPA1PSKWPA2PSK/AES&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 60&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11b/g/n NONE&amp;nbsp;&amp;nbsp; In6&amp;nbsp;&amp;nbsp; ACER-PC_Network&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 34:08:04:d1:bb:a8&amp;nbsp;&amp;nbsp; WPA1PSKWPA2PSK/TKIPAES 24&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11b/g/n NONE&amp;nbsp;&amp;nbsp; In6&amp;nbsp;&amp;nbsp; JS_GW&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 00:50:7f:e3:08:84&amp;nbsp;&amp;nbsp; WPA1PSKWPA2PSK/TKIPAES 65&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11b/g/n BELOW&amp;nbsp; In6&amp;nbsp;&amp;nbsp; ittraining_1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 28:10:7b:ef:8d:20&amp;nbsp;&amp;nbsp; WPA1PSKWPA2PSK/TKIPAES 89&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11b/g/n NONE&amp;nbsp;&amp;nbsp; In6&amp;nbsp;&amp;nbsp; ittraining_3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 00:90:cc:f4:d5:a4&amp;nbsp;&amp;nbsp; WPA1PSKWPA2PSK/TKIPAES 29&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11b/g/n BELOW&amp;nbsp; In11&amp;nbsp; IPxnase&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 00:24:a5:f4:c5:09&amp;nbsp;&amp;nbsp; WPA1PSKWPA2PSK/TKIP&amp;nbsp;&amp;nbsp;&amp;nbsp; 20&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11b/g&amp;nbsp;&amp;nbsp; NONE&amp;nbsp;&amp;nbsp; In11&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1c:bd:b9:b0:f2:c8&amp;nbsp;&amp;nbsp; WPA1PSKWPA2PSK/TKIPAES 10&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11b/g/n BELOW&amp;nbsp; In11&amp;nbsp; linksys&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 00:22:6b:7c:f2:43&amp;nbsp;&amp;nbsp; WPA1PSKWPA2PSK/TKIPAES 34&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11b/g/n NONE&amp;nbsp;&amp;nbsp; In&amp;nbsp;# start dhcp client to get IP from APudhcpc -i ra0 -s /bin/udhcpc.script &amp;amp;V.	References----------------------RT2870STA.datiwpriv_usage.txt                  </description>
		<pubDate>Tue, 02 Oct 2012 15:15:11 +0800</pubDate>
	</item>
	<item>
		<title>嵌入式系統導論_講義附錄</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8958</link>
		<description>To 本班同學 : 嵌入式系統導論_講義附錄參考附件檔案&amp;nbsp;Slide 於附件中 (just talking )1)嵌入式系統導論_20120823.pdf2)下載「5/15嵌入式應用實務經驗大公開講座簡報檔&amp;nbsp;3)&amp;nbsp;20101016 嵌入式系統開發之道講座 from 黑狗 大        </description>
		<pubDate>Thu, 23 Aug 2012 11:30:36 +0800</pubDate>
	</item>
	<item>
		<title>我走過的嵌入式軟體開發之路</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8795</link>
		<description> 嵌入式技術
欲打印此文章，從您的瀏覽器菜單中選擇“文件”後再選“打印”。
EE人生：我走過的嵌入式軟體開發之路
上網時間:2012年07月13日隨著專為嵌入式系統編程人員所設計的《Embedded System 
Design》平面雜誌劃下句點，我們更能看出未來的嵌入式軟體設計趨勢將更強調自動生成的程式碼，而不再那麼重視手寫編程了。

《Embedded System Design》最早在1988年以《Embedded Systems 
Programming》(ESP)的名稱出刊時，我才剛高中畢業。就像當時大多數人一樣，我從來沒聽說過「嵌入式系統」一詞，也沒想太多深藏於另一種產品中的電腦形式。六年後，我取得了電子工程師的學位，也像1990年代中期的許多電子工程師一樣找到了一份嵌入式軟體設計工作(而非硬體設計)。不久，我在一位同事的辦公桌上看到了這本雜誌，馬上就訂閱而且成了忠實讀者。

早期發展

1990年代初的情形就和現在一樣，學校中從來沒教過如何編寫出可靠的嵌入式軟體等專業知識。我在大學中唯一上過一門有關編程的課就是FORTRAN；後來才知道曾有過兩次實作課程學習組合語言和C語言編程就是我在編寫嵌入式軟體方面僅有的正規教育。我大多經由工作以及這份雜誌的內容學習，從這些篇章間第一次學會了如何編寫元件驅動程式、移植並使用作業系統、滿足即時的期限要求、建置有限狀態機等技巧，以及除C和組合語言以外其它編程語言的優缺點、遠端除錯與JTAG等等。

在那個時代，擔任韌體開發人員的我每天日常工作就是和英特爾hex文件、元件編程器、UV擦除器、僅kb容量的記憶體、8/16位元處理器、電路模擬器與ROM監視器等東西打交道。數據手冊有如就像書本一樣地多又厚，全部集中在一起的話就可以佔滿整個書架。我在我的辦公桌上的 
HP-UX 
工作站編寫韌體程式，後來必須到樓下實驗室去燒晶片，插入原型板中，再用ICE進行測試與除錯。我還記得有一個特別棘手的專案，所用的編譯器和元件編程器距離唯一可用的目標硬體8英哩遠；而一個單色的紅光 
LED 和一款滿是灰塵的示波器就堆在我的除錯工具箱附近。

我也和你一樣在1990年代中期就有網際網路可用，但除了特定的幾個FTP站點(還有人記得sunsite.unc.edu的FTP嗎？或Gopher？)以外，當時的網路並沒有太多對我的工作有用的資訊，大多是一些閃爍的標題文字以及The 
Hampster 
Dance(它直到現在都還存在呢！)；而亞馬遜(Amazon)也還只是當時世界上最大的河流。那時也還沒有Embedded.com或EETimes.com。為了學習軟體和硬體的最佳實作途徑，我晚上還在進修MSEE和CS課程，同時也常參與嵌入式系統大會(ESC)。

當時，我記得也沒有任何有關嵌入式編程的書籍。我發現有關C語言的每一本書都是從寫&quot;Hello, 
World&quot;開始介紹起，但都十分抽象，最後也都未能提到如何解決週邊控制、中斷服務程序、連接組合語言程序與作業系統(無論是否為RTOS)等問題。因此，多年後當Jack 
Ganssle問我時，我不知哪來的勇氣認為自己能夠針對嵌入式C編程領域所欠缺的部份撰寫一本書，後來也真的和O&#039;Reilly簽約，開始著手寫書──但我並沒在這本書一開始，而是到了最後才介紹用 
RS-232 移植編寫&quot;Hello, World&quot;。

到了1998年，在多次參與嵌入式系統大會後，有機會認識了《Embedded System Design》的主編Lindsey 
Vereen。除了寫書以外，我還曾經為《Embedded System 
Design》寫過幾篇文章，因而Lindsey已經對於我解釋技術差異的能力留下深刻印象。不過，當Lindsey告訴我他正在尋找一位技術編輯人選時，那時還不知道他屬意的人就是我。

未來的發展趨勢

從我第一次接觸到這本雜誌，就與它結下了不解之緣；接著先是技術編輯到後來成為主編及其後的特約編輯，這一直是我在個人職業生活中最精彩的一部份。在這本《Embedded 
System 
Design》創辦後的前十年，我自己就是這本雜誌及其中許多專欄作家和特約編輯的忠實讀者，到了第二個十年，我認為自己的努力更有助於使其成為一個提供讀者交換關鍵設計理念、實作以及產業學習時更有價值的討論場域。而今，儘管我能瞭解為什麼這本雜誌光靠現有的平面廣告再也撐不下去了，但對於它結束發行還是感到傷心與不捨。

回想過去的這段時光，嵌入式軟體設計領域真的發生了許多改變。時至今日，組合語言已經很少被用到了，C和C++就更不用說了。 EPROM 
及其元件編程器與UV擦除器已被快閃記憶體與開機載入程式所取代。匯流排寬度與記憶體容量也顯著地增加了。昂貴的電路模擬器與 ROM 
監示器已經轉型為較便宜的JTAG除錯。 ROM-DOS 已被微軟的任何嵌入式Windows作業系所取代。而開放來源的Linux由於發展得相當不錯，不但限制 
RTOS 產業的成長，同時也成為我們期望能更專精以便為履歷表加分的技術。

那麼，未來將會發生什麼呢？嵌入式編程人員在2020年、2030年或2040時的日常生活與體驗又會是什樣子的呢？在此，我提出將影響未來這些時間點的三大發展趨勢，特別是其中每一個趨勢已經開始發生了。

趨勢一：32位元CPU實現大量應用

我的第一個預測是低成本、低功耗且高整合的微控制器將為32位元帶來最高度的大量應用領域──最佳例子就是當今的ARM Cortex-M 系列。8位元和16位元 
CPU 將隨元件過時逐漸減少應用量。雖然你可能已在為32位元處理器編程，而發現目前仍是8位元與16位元處理器推動整體 CPU 
晶片銷售量的現況，但其實我指的是像基於 8051 
及其它30-40前前那種指令集架構的微處理器。這些舊式架構在今日仍十分普遍，只是因為特定嵌入式處理所需的低利潤、大量應用必須竭盡所能地節省BOM成本的每一分錢。

8位元和16位元架構的限制對於必須使用它們的嵌入式系統開發人員帶來許多方面的挑戰。首先，由於有限的位址匯流排寬度導致記憶體容量受限、還有記憶體庫、分割技術以及其他設法超越那些限制的變通辦法。其次，這些 
CPU 
在決策方面的效果優於其數學運算──這是因為缺乏有效處理較大整數的能力，而且也沒有浮點運算性能。最後，這些舊式的處理器也缺乏能夠執行像Linux等大型網際網路作業系統的能力，同時也缺乏由 
MMU 所提供的安全與可靠性保護。

當然，總會存在許多相當具成本限制的運算應用，所以我的預期並不是指8位元和16位元架構被完全淘汰，而是基於先進指令集架構與電晶體幾何的32位元微處理器整體價格(包括BOM成本與功耗)逐漸下滑，最後將會贏在價格上。這將可為設計人員帶來更充裕的電腦運算性能，並有助於簡化工作。

趨勢二：複雜度推動C以外的語言發展

我的第二個預測是C編程語言在嵌入式系統領域佔優勢主導地位的美好時光已經屈指可數了。

請不要誤會我的意思，C語言是一種我更能掌握且很喜歡的編程語言。但是，正如你可能知道的，C根本就無法勝任打造需要超過1百萬條程式碼的系統。然而，1百萬多行程式碼的系統卻是長久以來推動編程領域的嵌入式軟體所需的複雜程度。有些事情就是得具有一定的複雜度。

此外，還有嵌入式系統開發人員平均年齡迅速在增加中，而C語言通常不再於大學課程中教授等等迫在眉睫的問題。因此，即使每個產業對於嵌入式智慧的要求越來越高，熟悉或有經驗的C語言編程人員人數卻在不斷減少中。有些事也得要有人員才能完成啊！

但是，什麼樣的替代語言可用於建立即時軟體、直接地操縱硬體，以及快速地移植到眾多指令集架構呢？它當然不會是 C++ 或 Ada 或 Java 
──這些都已經被試過，而且發現其不足之處了。然而，在經歷過許多CPU產品系列以及試過這麼多其它語言後，開發一種新的編程語言可能也不見得是我們想要的答案。 

因此，根據系統規格來看，我預期能為我們可靠地自動生成數百萬行C程式碼的工具，最終將成為新的替代方案。以目前符合這種趨勢的現有工具來看，我們可以密切注意Miro 
Same用於事件導向編程的開放來源 Quantum Platform 架構及其免費的 Quantum Model 
繪圖建模工具選項。你可能並不喜歡當今自動生成程式碼的作法，但我保證一旦你在為狀態機架構進行編程時，你將看到這整個結構的好處，以及它可為編程帶來的效率。

對於這一類的工具而言，我認為C語言是一種相當普遍的輸出語言，這是因為C語言能直接操縱硬體暫存器，而且為大量市場開發的每一種處理器都有相容的編譯器可用。其實我真的期望持續要求具有技能與興趣的人員能為其協助調整程式碼生成或編寫元件驅動器的性能，使其得以更密切地整合於硬體中。

趨勢3：連接性提升安全的重要性

越來越多的嵌入式系統之間密切地彼此互連，並連接到網際網路。你可能聽說過「物聯網」(Internet of 
Things；IoT)以及「泛在運算」(ubiquitous computing)，也可能已經把 TCP / IP 
加進你的設計中。但連接性還有太多我們從未瞭解到的層面，或許其中最明顯的就是安全性。

互連的設備離不開安全性，因此，我們必須從一開始就為連接設備加進安全性的設計。觀察這整個產業，大多數的嵌入式設計人員很大程度上並不熟悉安全性。當然你已經讀過加密演算法，也知道幾個相關的技術名詞。但大部份的嵌入式社群就和安全性設計人員一樣地似懂非懂，而其組織也無法為其帶來太多協助。安全性的強度僅僅和這一系統鏈中最薄弱的環節一樣。

這種狀況必須改變。正如快閃記憶體取代UV可擦除的 EPROM 
一樣，在未來的幾十年，透過網路下載增補程式與軟體升級也將成為主要的機制。我們首先必須架構出安全的系統，然後才可能安全地進行下載，從而使我們的產品有能力免於駭客的威脅與攻擊。

結語

無論未來的情況如何發展，我確定嵌入式軟體開發仍將會是一個具吸引力與挑戰性的專業領域。而且你也會看到我繼續在Embedded.com、EmbeddedGurus.com以及twitter.com/embeddedbarr發表有關嵌入式領域的相關文章。

本文作者Michael Barr是Barr Group的技術長，專精於安全且可靠的即時運算嵌入式軟體架構。Michael 
Barr曾任教於馬里蘭大學(University of Maryland)與約翰霍普金斯大學(Johns Hopkins 
University)；他還曾發表過三本書，以及超過65篇有關嵌入式系統設計專文。

編譯：Susan Hong

(參考原文：Trends in embedded software design，by Michael Barr)
此文章源自《電子工程專輯》網站:http://www.eettaiwan.com/ART_8800670659_676964_NT_cbf9e5e1.HTM 
http://www.eettaiwan.com/ART_8800670659_676964_NT_cbf9e5e1.HTM&amp;nbsp; </description>
		<pubDate>Tue, 17 Jul 2012 17:34:13 +0800</pubDate>
	</item>
	<item>
		<title>譯：Android 被 Linux kernel 社群開除</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8770</link>
		<description>原文：http://www.kroah.com/log/linux/android-kernel-problems.html在 Linux kernel 2.6.33 版本，Android 程式碼，已經被移除。很多人開始詢問我到底發生了什麼事？Android 下一步又該怎麼辦？所以，以下就是我對這整件事情的意見……首先，我要說，我是很喜歡 Android 手機平台。直到上週，我還是每天，使用我買的 developer G1，它完美的運作，讓用戶我非常高興。從技術的角度，我也對 Android 感到高興。讓人驚奇，Google 運用 Linux 內核，純粹就用傳統的 Linux 系統，創造出一個具移植性，而且可靠的手機平台。這個平台是這麼特別，你甚至可以在手機上，換上一個 Linux 作業系統的 image 檔，兩種版本都可運作正常，完全不需任何修改。Android 同時也解決了收機製造商，多年以來的一些問題：一個免費版本的 Java，及一個統一的應用程式中介層，讓程式人員針對它開發出軟體，可以運行在所有 Android 的手機上。因為這樣，所有現有的「Linux 手機聯盟」，不是已經群體滅亡，倖存的應該也會很快就默默的消失。這有哪裡不對？發生什麼事，讓 Android 程式碼，被從 Linux 核心刪除？簡單說，沒有人關心 Android 程式碼了，所以就刪了吧。就像我以前所聲明的，核心程式碼，分支版本，必須努力整併進主要版本，不然就會被刪除。但是關於這點，有更大的問題存在。Android 內核，並非只是在 drivers/staging/android 子目錄，的幾個怪異驅動程式而已。為了能讓 Android 運作，你需要用他們所新增的 lock type，並且用他們的安全模式，才能跟 Linux 內核掛勾上。為了要寫 Android 上使用的 驅動程式，你需要正確的整合新的 lock，有時還要跟怪異的安全模式打交道。對了，還有一個完全不同的顯示硬體 frame buffer 架構。&amp;nbsp;這意謂任何為 Android 平台寫的驅動程式，因為跟 Google 內核分支有相依性，所以就不能整併進主要內核分支，最終也不能進 kernel.org 內核分支。就因為這樣，Google 已經造成很多的驅動程式，很多與平台相關的程式碼，不能整進主要內核分支。實質上，這已經變成了幾個特定製造商，所倚賴的內核分支。現在 Linux 內核的的幾個分支版本，是依照幾個主要的發行版本，所制定的，目前相安無事。但是因為 Google 不想讓他們的程式碼，整併入主流的分支。Google 所寫出的驅動程式及平台相關的程式，被鎖住無法回饋給內核社群。而內核社群，已經花很多年，告訴這些 Linux 發行版本的公司，把他們的內核整併進來。然後這些發行商，他們就可以，套用新的安全性修正，套用大量且快速異動的程式碼。這些公司有聽到呼籲，你可以看到他們持續在他們所發行的版本，更新他們的內核。但是現在他們被卡住了，那些使用 Android 相關平台或是驅動的公司，不能回饋給他們的上游。造成這些發行商，在回護及開發內核上，要花更大的功夫。想要把 Android 內核碼整併進主分支，要如何做呢？當 Android 的程式碼，整進一的臨時的分支，幾位核心程式的開發人員，會審核程式碼，然後指出該清理、該改變的地方，這樣程式碼才能夠被接受。有一些改變，會影響到內核跟使用者空間的界限，所以有些 Android 上的用戶空間的邏輯，也會因為內核的改變，而需跟著改變。但這可以免除了 Google 以外的員工，因為引進 Android 引起的不必要修改。那，下一步呢？我真的不知道。Google 似乎不再願意整併程式碼到上游。有些公司嘗試拿掉 Android 規格的介面，然後將程式碼上游。但這是需要很大的力氣，又顯得沒有必要。衷心希望我希望 Google 能回來，修正他們的程式，整併進主分支，然後回饋給上游。並停止他們對許多 Linux 鑲入式系統公司，所造成的障礙。我以前曾經私底下幫忙解決這些問題，現在及以後將公開支持並幫忙解決這些問題，但我需要 Google 開發人員的幫忙，沒有他們，什麼都改不了。好消息是，內核及使用者空間程式介面的改變，將不會影響任何 Android 應用程式的程式碼。所有這些改變，可以適用在整個系統，完全沒有問題。我將在 CE Linux 論壇 2010 的演講上，談論 Android 的這一團亂。希望在這之前，情況會有所改善。不然 CELF 將秉持長久以來的慣例，在會議上發演講稿，大聲斥責他們已經幹出來的壞事情。
   </description>
		<pubDate>Tue, 10 Jul 2012 08:52:18 +0800</pubDate>
	</item>
	<item>
		<title>TTS Text-to-speech</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8648</link>
		<description>好東西~TTS Text-to-speech&amp;nbsp;輸入進去的文字轉成真人發音的語音檔!工研院資通所 前瞻技術中心http://atc.ccl.itri.org.tw/
AT&amp;amp;T Natural Voices&amp;reg; Text-to-Speech Demohttp://www2.research.att.com/~ttsweb/tts/demo.php </description>
		<pubDate>Thu, 07 Jun 2012 07:36:04 +0800</pubDate>
	</item>
	<item>
		<title>附件: 無線個人區域網路(WPAN)技術</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8631</link>
		<description>&amp;nbsp;無線個人區域網路(WPAN)技術發展與應用概論 </description>
		<pubDate>Tue, 05 Jun 2012 10:50:45 +0800</pubDate>
	</item>
	<item>
		<title>Serial Programming -VMIN &amp; VTIME</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8627</link>
		<description>Read(2) 何時Return ?在Raw data 的輸入程序模式下, 輸入的資料不會被組合成一行而輸入後的處理功能 (清除, 殺掉, 刪除, 等等.) 都不能使用. 這個模式有兩個控制參數: c_cc[VTIME] 設定字元輸入時間計時器, 及 c_cc[VMIN] 設定滿足read(2)的最低字元接收個數.VMIN = 0 and VTIME = 0This is a completely non-blocking read - the call is satisfied immediately directly from the driver&#039;s input queue. If data are available, it&#039;s transferred to the caller&#039;s buffer up to nbytes and returned. Otherwise zero is immediately returned to indicate &quot;no data&quot;. We&#039;ll note that this is &quot;polling&quot; of the serial port, and it&#039;s almost always a bad idea. If done repeatedly, it can consume enormous amounts of processor time and is highly inefficient. Don&#039;t use this mode unless you really, really know what you&#039;re doing.如果 VMIN = 0 且 VTIME = 0, Non-bloking Read模式 ,&amp;nbsp;read(2)&amp;nbsp;立即Return目前已存在的字元組個數, 或者 Return 0 表示沒有資料, 你也可以用 fcntl(uartfd, F_SETFL, FNDELAY); =&amp;gt; 設成Nonlblocking ModeVMIN = 0 and VTIME &amp;gt; 0This is a pure timed read. If data are available in the input queue, it&#039;s transferred to the caller&#039;s buffer up to a maximum of nbytes, and returned immediately to the caller. Otherwise the driver blocks until data arrives, or when VTIME tenths expire from the start of the call. If the timer expires without data, zero is returned. A single byte is sufficient to satisfy this read call, but if more is available in the input queue, it&#039;s returned to the caller.&amp;nbsp;Note that this is an&amp;nbsp;overall&amp;nbsp;timer, not an&amp;nbsp;intercharacter&amp;nbsp;one.如果 VMIN = 0 且 VTIME &amp;gt; 0, VTIME 將被當做逾時設定值.&amp;nbsp;&amp;nbsp;&amp;nbsp;read(2)&amp;nbsp;Return&amp;nbsp;的情況為讀取到單一字元, 或者超過 VTIME 所定義的時間 (t =VTIME *0.1 s). 如果超過 VTIME 所定義的時間, 則不會傳回任何字元.VMIN &amp;gt; 0 and VTIME &amp;gt; 0A&amp;nbsp;read()&amp;nbsp;is satisfied when either VMIN characters have been transferred to the caller&#039;s buffer, or when&amp;nbsp;VTIME tenths expire between characters.&amp;nbsp;Since this timer is not started until the first character arrives, this call can block indefinitely if the serial line is idle.&amp;nbsp;This is the most common mode of operation, and we consider VTIME to be an&amp;nbsp;intercharactertimeout, not an&amp;nbsp;overall&amp;nbsp;one.&amp;nbsp;This call should never return zero bytes read.如果 VMIN &amp;gt; 0 且 VTIME &amp;gt; 0, VTIME 將被當做接收字元間隔的計時器. read(2)&amp;nbsp;Return&amp;nbsp;的條件為 接收到 VMIN 個數的字元, 或兩個字元的間隔時間超過 VTIME 所定義的值. 計時器只會在第一個字元收到後才會啟動.且每讀到一個字元後會再重新計時.VMIN &amp;gt; 0 and VTIME = 0This is a counted read that is satisfied only when at least VMIN characters have been transferred to the caller&#039;s buffer - there is no timing component involved. This read can be satisfied from the driver&#039;s input queue (where the call could return immediately), or by waiting for new data to arrive: in this respect the call could block indefinitely. We believe that it&#039;s undefined behavior if nbytes is less then VMIN.如果 VMIN &amp;gt; 0 且 VTIME = 0, VMIN 設定為&amp;nbsp;read(2)&amp;nbsp;Return&amp;nbsp;的最低字元接收個數. 由於 TIME 是零, 所以計時器將不被使用.         </description>
		<pubDate>Mon, 04 Jun 2012 13:34:00 +0800</pubDate>
	</item>
	<item>
		<title>[技術文章] tftpd的安裝與啟動方式：</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8579</link>
		<description>在接觸Embedded Linux時，我們會更換nand flash 裡的 u-boot、kernel、rootfs這三種映像檔，而我們最常使用的server就是tftpd。u-boot支援tftpd的功能，讓我們可以透過網路的方式，將nand flash裡舊有的u-boot、kernel、rootfs等的映像檔更換成為新編譯的映像檔。那我們要如何安裝tftpd，讓target board上的u-boot可以與我們PC上的的Linux 溝通呢？tftpd的安裝與啟動方式：步驟一：$sudo apt-get install tftpd xinetd步驟二：$sudo vim /etc/xinetd.d/tftp(將以下的內容寫入到tftp裡面)service tftp{&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;socket_type &amp;nbsp; &amp;nbsp; = dgram&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;protocol &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= udp &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= yes&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;user &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= root&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;server &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= /usr/sbin/in.tftpd&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;server_args &amp;nbsp; &amp;nbsp; = -s /var/lib/tftpboot&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;disable &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = no&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;per_source &amp;nbsp; &amp;nbsp; &amp;nbsp;= 11&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;cps &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = 100 2&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;flags &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = IPv4};wq＊註解：server_args &amp;nbsp;= -s &amp;nbsp;/var/lib/tftpboot &amp;nbsp;這個意思是指，透過tftpd傳輸檔案時所開放的目錄路徑。$sudo /etc/init.d/xinetd start$sudo netstat aunp | grep xinetdudp &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 0.0.0.0:69 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0.0.0.0:* &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1568/xinetd&amp;nbsp;這樣tftpd就已經可已開始使用囉!艾鍗學院 Andre     </description>
		<pubDate>Sat, 26 May 2012 17:24:20 +0800</pubDate>
	</item>
	<item>
		<title>Write Mifare Card</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8541</link>
		<description>Write Mifare CardAt start, to put NDEF content that can be readed by other readers, the tag have to be NFC Forum compiliant.&amp;nbsp;To bring Mifare Classic as NFC Forum enabled tag, you have to follow the dedicated application note:&amp;nbsp;&amp;nbsp;&quot;Mifare Classic as NFC Forum Enable Tag&quot; from NXP.This application note explain how to use MAD and Mifare Classic sectors in order to put NDEF content in sectors, so you need to know about MAD, by reading (and implementing) &quot;MIFARE Application Directory (MAD)&quot; from NXP.These files are also useful:Mifare Std as NFC Forum Enabled Tag - Extensions for Mifare standard 1k/4k as NFC Forum Enable Tag (v.1.1, 2010-10-01)NXP Type MF1K/4K Tag Operation - Storing NFC Forum data in Mifare Standard 1k/4k (v.1.1, 2010-10-01)Once you have a tag that can handle NDEF content, you need to learn how to forge NDEF message, that contains NDEF records. To do this, you need to read NFCForum-TS-NDEF_1.0 from NFCForum and you need to understand types described in :NFCForum-SmartPoster_RTD_1.0,NFCForum-TS-GenericControlRTD_1.0,NFCForum-TS-RTD_1.0 andNFCForum-TS-RTD_Text_1.0Finally, I should point to you two projects that you can be interested in :- libfreefare, that allow mifare manipulation and provide an example to write ndef on Mifare Classic and Mifare DESFire tag.- libndef that enable you to simply manipulate NDEF messages and records in Object Oriented way.使用 aplay to play wave file&amp;nbsp;aplay -t raw -c 1 -f S16_LE -r 8000 test2.pcm&amp;nbsp; -t: type raw表示是PCM&amp;nbsp; 
-c: channel 1&amp;nbsp; 
-f S16_LE: 
Signed 16bit-width Little-Endian&amp;nbsp; -r: sample rate 8000&amp;nbsp; PCM是最raw的音頻數據，沒有任何頭信息。WAV文件就是PCM+頭信息，頭信息就是上述的聲道數，sample 
rate這些。所以WAV文件可以直接播放，而PCM需要手動指定這些信息之後才能播放     </description>
		<pubDate>Mon, 21 May 2012 00:15:07 +0800</pubDate>
	</item>
	<item>
		<title>Linux Serial Programming</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8486</link>
		<description>Serial Programming Guide&amp;nbsp;http://www.easysw.com/~mike/serial/serial.html
 </description>
		<pubDate>Thu, 10 May 2012 22:49:31 +0800</pubDate>
	</item>
	<item>
		<title>Ouput from make</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8477</link>
		<description></description>
		<pubDate>Tue, 08 May 2012 20:54:29 +0800</pubDate>
	</item>
	<item>
		<title>UBIFS</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8447</link>
		<description></description>
		<pubDate>Thu, 03 May 2012 01:12:19 +0800</pubDate>
	</item>
	<item>
		<title>The Linux USB sub-system</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=8136</link>
		<description>To 就業班 學員,請先studyThe Linux USB sub-systemhttp://linuxusbguide.sourceforge.net/USB-guide-1.0.9/book1.html
 </description>
		<pubDate>Sat, 24 Mar 2012 11:27:32 +0800</pubDate>
	</item>
	<item>
		<title>倚天中文字型輸出Framebuffer</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=7454</link>
		<description></description>
		<pubDate>Mon, 14 Nov 2011 11:50:30 +0800</pubDate>
	</item>
	<item>
		<title>嵌入式系統開發之道講座 slide</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=7321</link>
		<description>&amp;nbsp;
&amp;nbsp;

&amp;nbsp;
&amp;nbsp;
&amp;nbsp;
上星期六(20101016)由艾鍗學院舉辦的的嵌入式系統開發之道講座的過程算是相當順利，唯一可惜的是大黑狗沒把時間控制好，有些topic無法講得太深入，這是大黑狗一直以來的毛病，雖然近來已經試著改善，但演講時看到台下朋友們認真的眼神，難免就會在某些slide花上太多時間。 
當天演講時間只有兩小時，不可能把書中所有topic講到，所以把主題壓縮為三個主要部份：1. 何謂嵌入式系統開發之道
2. 電子產品開發專案的生命週期
3. 嵌入式系統從業人員的職涯發展
依照大黑狗一直以來的作法，我把當日的投影片share出來，您可以拿來作任何應用，只要注明出處即可。您可到 這裡 (http://www.badongo.com/file/24384359)下載，懶得下載的話，也可以到SlideShare 直接看 (http://www.slideshare.net/ealin/20101016 &amp;nbsp;，雖然SlideShare已經做得很不錯了，但轉檔時還是會把一些效果濾掉，有些格式設定也會變得亂亂的，但瑕不掩瑜啦)。
大黑狗持續地把以前的一些投影片作些風格上的修改-以前作的投影片往往都有文字太多的問題，這種投影片打出來時，聽眾光忙著看這些字，完全沒辦法聽進去演講者講的內容，這對聽眾與演講者都是是很可惜的事情。這份投影片也只改了一部分，後面還來不及修正 – 大黑狗持續改善中，有新的版本會再release出來。 </description>
		<pubDate>Sat, 29 Oct 2011 19:44:08 +0800</pubDate>
	</item>
	<item>
		<title>News: Qualcomm DragonBoard</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=7113</link>
		<description> 嵌入式技術
高通推DragonBoard板　跳入「嵌入式」戰局
上網時間:2011年10月03日一直以來都直接與手機OEM和ODM廠商合作的高通(Qualcomm)，在本屆「嵌入式系統大會」(Embedded Systems Conference, ESC)上發佈一款全新設計的‘ DragonBoard ’設計，加入了‘嵌入式’戰局。 

藉由將該公司的 Snapdragon 應用處理器從蜂巢式數據機連接設計中分離而出，“我們現在能賦予 DragonBoard 更寬廣的可用性”，且客戶無需被迫簽署昂貴的 CDMA 授權， Qualcomm 業務開發資深總監 Tia Cassett 說。 

Qualcomm 為 DragonBoard 訂定的目標價是300美元，這款新開發板瞄準的客戶包括應用開發人員、個人保健產品設計者、消費性裝置和工業設備，以及工程系學生或各大專院校等。“我們希望他們能開發出前所未有的創新應用，”Cassett說。 

DragonBoard包含一個搭載Qualcomm Snapdragon APQ8060處理器的主板；WiFi/Bluetooth連接子板；感測器子板；驅動器和其他零組件，以及Android作業系統。 

為使用其他類型的感測器，舉例來說，如化學感測器，使用者可以使用新的感測器子板。“是非常客製化的設計，”Cassett表示。 

當然，市面上有許多不具備蜂巢式數據機的應用處理器，它們也都瞄準像平板電腦或智慧型電視這類消費性裝置。而當問及 APQ8060 的特殊之處時，Cassett指出，更強大的處理能力，是該產品的最大特色。 

這塊開發板搭載了APQ8060處理器，它以全新的雙核心Scorpion CPU架構為基礎，提供每核心達1.5GHz的時脈。該處理器結合了非同步雙核SMP微架構，能讓每個核心獨立運作。這顆應用處理器提供完整的多媒體1080p HD視訊和Dolby 5.1音訊，以及Qualcomm自有的Adreno 220 GPU。 



Qualcomm的DragonBoard。


Cassett表示，德州儀器(TI)的BeagleBoard為Qualcomm帶來了一些靈感。BeagleBoard具備低功耗、低成本特性，搭載TI的OMAP3530系統單晶片(SoC)。但她強調，“我們更進了一步。我們的DragonBoard可提供更多。” 


編譯： Joy Teng 

(參考原文： Qualcomm jumps into ‘Embedded’ fray，by Junko Yoshida) 
此文章源自《電子工程專輯》網站:http://www.eettaiwan.com/ART_8800652717_676964_NT_429d1f26.HTM http://www.eettaiwan.com/ART_8800652717_676964_NT_429d1f26.HTM  </description>
		<pubDate>Mon, 03 Oct 2011 00:37:08 +0800</pubDate>
	</item>
	<item>
		<title>Audio</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=7111</link>
		<description></description>
		<pubDate>Sat, 01 Oct 2011 22:28:03 +0800</pubDate>
	</item>
	<item>
		<title>如何撰寫一個serial port的驅動程式</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=7003</link>
		<description>

簡介
RS232是kernel中常用到的一種週邊元件，在以前主要是拿來連接終端設備的通訊介面，而今日則是常被拿來做控制或者和其它設備通訊的介面，因為其硬體簡單及成本低所以會被很多設備做為最基本的通訊介面，因為其發展有很長一段時間，所以在Linux中有為它特別規劃一組軟體堆疊，主要分為實體控制層以及上層的終端控制層，其架構如下:

初始化所以通常我們要寫的是實體層的驅動程式，在driver的進入點，若是PCI介面，則先註冊一個PCI的call back function，若是local bus則是可以註冊一個platform device call back function，當系統進入你所註冊的call back function，必須對你所使用的硬體介面位址做一個remapping的動作，就是將實體位址轉換成虛擬位址，接著後面的所有程式碼都要使用這個虛擬位址，這時要開始初始化你的硬體及driver，首先建立一個struct tty_driver的資料結構，其宣告如下：struct tty_driver {int magic; /* magic number for this structure */struct cdev cdev;struct module *owner;const char *driver_name;const char *name;int name_base; /* offset of printed name */int major; /* major device number */int minor_start; /* start of minor device number */int minor_num; /* number of *possible* devices */int num; /* number of devices allocated */short type; /* type of tty driver */short subtype; /* subtype of tty driver */struct ktermios init_termios; /* Initial termios */int flags; /* tty driver flags */int refcount; /* for loadable tty drivers */struct proc_dir_entry *proc_entry; /* /proc fs entry */struct tty_driver *other; /* only used for the PTY driver *//** Pointer to the tty data structures*/struct tty_struct **ttys;struct ktermios **termios;struct ktermios **termios_locked;void *driver_state; /* only used for the PTY driver *//** Interface routines from the upper tty layer to the tty* driver. Will be replaced with struct tty_operations.*/int (*open)(struct tty_struct * tty, struct file * filp);void (*close)(struct tty_struct * tty, struct file * filp);int (*write)(struct tty_struct * tty,const unsigned char *buf, int count);void (*put_char)(struct tty_struct *tty, unsigned char ch);void (*flush_chars)(struct tty_struct *tty);int (*write_room)(struct tty_struct *tty);int (*chars_in_buffer)(struct tty_struct *tty);int (*ioctl)(struct tty_struct *tty, struct file * file,unsigned int cmd, unsigned long arg);long (*compat_ioctl)(struct tty_struct *tty, struct file * file,unsigned int cmd, unsigned long arg);void (*set_termios)(struct tty_struct *tty, struct ktermios * old);void (*throttle)(struct tty_struct * tty);void (*unthrottle)(struct tty_struct * tty);void (*stop)(struct tty_struct *tty);void (*start)(struct tty_struct *tty);void (*hangup)(struct tty_struct *tty);void (*break_ctl)(struct tty_struct *tty, int state);void (*flush_buffer)(struct tty_struct *tty);void (*set_ldisc)(struct tty_struct *tty);void (*wait_until_sent)(struct tty_struct *tty, int timeout);void (*send_xchar)(struct tty_struct *tty, char ch);int (*read_proc)(char *page, char **start, off_t off,int count, int *eof, void *data);int (*write_proc)(struct file *file, const char __user *buffer,unsigned long count, void *data);int (*tiocmget)(struct tty_struct *tty, struct file *file);int (*tiocmset)(struct tty_struct *tty, struct file *file,unsigned int set, unsigned int clear);struct list_head tty_drivers;};
在這個資料結構中其中分為幾個部分，第一個部分是所以謂的callback function的註冊，在這些個callback function中你必須金對你有實現的部分給予註冊，若沒有就可以給予不註冊，但相對的你的驅動程式所支援的功能會較少。另一個部分則是驅動程式本身資訊的資料，如major number、starting minor number、tty device name等等，以下是一個例子：


struct tty_driver MySerialDriver;
#define MAX_PORTS 4
struct ktermios *my_termios[MAX_PORTS];
struct ktermios *my_termios_locked[MAX_PORTS];


memset(&amp;amp;MySerialDriver, 0 sizeof(MySerialDriver));
MySerialDriver.name = &quot;ttyN&quot;;
MySerialDriver.major = 40;
MySerialDriver.minor_start = 0;
MySerialDriver.minor_num = MAX_PORTS;
MySerialDriver.num = MAX_PORTS;
MySerialDriver.magic = TTY_DRIVER_MAGIC;
MySerialDriver.type = TTY_DRIVER_TYPE_SERIAL;
MySerialDriver.subtype = SERAL_TYPE_NORMAL;
MySerialDriver.init_termios = tty_std_termios;
MySerialDriver.init_termios.c_cflag = B9600 CS8 CREAD CLOCAL;
MySerialDriver.flags = TTY_DRIVER_REAL_RAW;
MySerialDriver.termios = my_termios;
MySerialDriver.termios_locked = my_termios_locked;


MySerialDriver.open = my_open;

以下為driver initialize的工作內容
1. allocate tty driver資料結構使用



struct tty_driver *mxvar_sdriver=alloc_tty_driver(MXSER_PORTS + 1);
2. 在allocate的tty driver資料結構中填入必要的資訊



mxvar_sdriver-&amp;gt;owner = THIS_MODULE; 
mxvar_sdriver-&amp;gt;magic = TTY_DRIVER_MAGIC; 
mxvar_sdriver-&amp;gt;name = &quot;ttyMI&quot;; 
mxvar_sdriver-&amp;gt;major = ttymajor; 
mxvar_sdriver-&amp;gt;minor_start = 0; 
mxvar_sdriver-&amp;gt;num = MXSER_PORTS + 1; 
mxvar_sdriver-&amp;gt;type = TTY_DRIVER_TYPE_SERIAL; 
mxvar_sdriver-&amp;gt;subtype = SERIAL_TYPE_NORMAL; 
mxvar_sdriver-&amp;gt;init_termios = tty_std_termios; 
mxvar_sdriver-&amp;gt;init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; 
mxvar_sdriver-&amp;gt;flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV;

3. 設定tty會使用的各個call back function


tty_set_operations(mxvar_sdriver, &amp;amp;mxser_ops);
而其中的mxser_ops設定如下: 

static const struct tty_operations mxser_ops = {
.open = mxser_open,
.close = mxser_close,
.write = mxser_write,
.put_char = mxser_put_char,
.flush_chars = mxser_flush_chars,
.write_room = mxser_write_room,
.chars_in_buffer = mxser_chars_in_buffer,
.flush_buffer = mxser_flush_buffer,
.ioctl = mxser_ioctl,
.throttle = mxser_throttle,
.unthrottle = mxser_unthrottle,
.set_termios = mxser_set_termios,
.stop = mxser_stop,
.start = mxser_start,
.hangup = mxser_hangup,
.break_ctl = mxser_rs_break,
.wait_until_sent = mxser_wait_until_sent,
.tiocmget = mxser_tiocmget,
.tiocmset = mxser_tiocmset,
};

4. 向tty_io註冊driver


retval = tty_register_driver(mxvar_sdriver);

5. 註冊 PCI client或者platform的driver, 等待其call back所設定probe程序


retval = pci_register_driver(&amp;amp;mxser_driver);

PCI client driver的資料結構如下：

static struct pci_driver mxser_driver = {
.name = &quot;mxser&quot;,
.id_table = mxser_pcibrds,
.probe = mxser_probe,
.remove = __devexit_p(mxser_remove)
};
或者


retval = platform_register_driver(&amp;amp;mxser_driver);platform client driver的資料結構如下：

static struct platform_driver moxaarm11_gmac_driver = {
.driver.name = DRV_NAME,
.probe = moxaarm11_gmac_probe,
.remove = moxaarm11_gmac_remove,

};


6. 這時HAL層(PCI or platform)若有找到該元件, 將會呼叫設定的probe call back function

probe call back function內做的事情
1. 取得所分配到的resource, 包含I/O及IRQ
2. 向kernel註冊所需的resource, 若是使用memory的方式來存取, 記得需要將取得的physical address用ioremap將其轉換為virtual address
3. 註冊IRQ service routine (ISR)
4. 針對每一個實體的port向上層tty做註冊


tty_register_device(mxvar_sdriver, brd-&amp;gt;idx + i, &amp;amp;pdev-&amp;gt;dev);


remove call back function內做的事情
1. 將取得resource釋放出來
2. 將已remap過的virtual address做unremap的動作
3. 取消已註冊的ISR
4. 針對每一個已註冊的實體port向上層tty做取消的動作


tty_unregister_device(mxvar_sdriver, brd-&amp;gt;idx + i);原則上remove的動作剛好都和probe做相反的動作 


各個operation call back function內做的事情
這些的call back function都會先經過tty_io的處理之後，才會再呼叫這些call back function。

open
這是當AP呼叫open()時會被呼叫的進入點，但是在呼叫你的open call back function之前，會先經過tty_io處理過，在你的open call back function中如何取得的minor number? 可以從tty_io傳給你的tty_struct structure 中的成員index取得(tty-&amp;gt;index)，你若有控制多port的serial port這時你就可以知道AP要open那一個port，另外linux是一個多工的作業系統，所以有可能多個AP會呼叫下來，也許會open同一個port，這時driver本身自已要記住該port已被open多少次，當是第一個open時需初始化該port，以及buffer的allocate，另外serial port的硬體設定是保留前一個設定，在open時不會做更動。

close
從call back的名字就可以知道，這是從AP的close()時的進入點，這個call back function應該檢查是否為最後一個close，也就之前已有多個open()之中的最後一個close(), 記得前面的open會記住被open幾次，在close則相對地減掉被open的數，在最後一次的close時，應將open中所取得的resource應全數release給kernel。

write
這是送資料的進入點, 通常我們都會先將資料放在自已的buffer, 之後再慢慢送, 而且通常會使用interrupt的方式來送, 而這個return值會是有多少bytes已存在你的buffer中

put_char
serial communication中有所謂software flow control, 它是用資料中兩個bytes XON(0x11), XOFF (0x13)來做這流量控制, 而當要送這個bytes時就會呼叫這一個call back function, 而且這兩個必須要馬上被送出, 不可放在buffer之中, 所以原則上會在這個call back function做一個flag記錄, 而在interrupt service routine中即時送出

flush_chars
這是清除本來在put_char中的資料, 若尚未送出將給予丟棄

write_room
檢查送的buffer還剩多少空間可以存放資料

char_in_buffer
已收進多少資料在driver buffer之中

ioctl
這是相對應AP的ioctl() API, 在linux的tty中已定義一些ioctl() command, 應給予支援, 你也可以自行定義一些ioctl()

set_termios
設定RS232如baud rate, data bits, stop bits等等, 將會使用struct termios來做設定資料結構

throttle
這是在做flow control用的, 在以往hardware不夠好的時候, flow control是軟體來實現, 而且由tty_io來控制, 現在硬體已比以前強了, 所以flow control部分將會由硬體來實現, 而這個將是停止送資料, 不用管是由software flow control or hardware flow control來的, 這個call back function被呼叫時, 就是停止送資料

unthrottle
這個動作也是在做flow control, 和上面的throttle相反, 則是開始送資料

stop
shutdown該UART port

start
啓動該port

hangup
這是在接modem時用的, 用在掛電話

break_ctrl
這是在送break訊號的控制

flush_buffer
這是清除在driver buffer中的資料, 將存放在buffer中尚未處理的資料全部給予丟棄

wait_until_sent
等待在buffer中尚未送出的資料全部送出, 而且需要block在這裏面

tiocmget
最得modem的訊號 CTS, DSR, DCD, RI

tiocmset
控制modem訊號 RTS, DTR

在了解各個call back function的定義及作業內容，這時寫driver的人就必須依照這樣的定義來撰寫serial port device driver. 最後最重要的是interrupt service routine, 原則上收送資料都是使用interrupt的方式來收送, 但是在送資料時, 應該是一次就將FIFO填滿, 而收的部分通常設定一個FIFO的high water就產生interrupt, 因為不可在FIFO滿的時候才產生interrupt, 這樣沒有緩衝時間來處理後面持續進來的資料, 容易造成FIFO overflow, 以上是RS232 device driver的大概說明, 其它還有許多細節的部分留待以後再說明
&amp;nbsp;
資料來源: Richman&#039;s blog&amp;nbsp;
&amp;nbsp;
&amp;nbsp; </description>
		<pubDate>Thu, 15 Sep 2011 20:04:39 +0800</pubDate>
	</item>
	<item>
		<title>ARM Linux Booting Flow</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=6734</link>
		<description></description>
		<pubDate>Sat, 13 Aug 2011 23:16:33 +0800</pubDate>
	</item>
	<item>
		<title>關於Socket option  --SO_LINGER option</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=6699</link>
		<description>&amp;nbsp;
&amp;nbsp;
&amp;nbsp;static struct linger&amp;nbsp; linger = {0, 0};&amp;nbsp;int lsize&amp;nbsp; = sizeof(struct linger);&amp;nbsp;setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&amp;amp;linger, lsize);
&amp;nbsp;
&amp;nbsp;---------------------
&amp;nbsp; SO_LINGER (see following NOTE) controls the action taken when unsent&amp;nbsp;&amp;nbsp;messages are queued on socket and a close(S) is performed. If the socket&amp;nbsp;&amp;nbsp;promises reliable delivery of data and SO_LINGER is set, the system will&amp;nbsp;&amp;nbsp;block the process on the close attempt until it is able to transmit the&amp;nbsp;&amp;nbsp;data or until it decides it is unable to deliver the information. A timeout:&amp;nbsp;&amp;nbsp;period, termed the linger interval, is specified in the setsockopt call&amp;nbsp;&amp;nbsp;when SO_LINGER is requested. If SO_LINGER is disabled and a close is&amp;nbsp;&amp;nbsp;issued, the system will process the close in a manner that allows the&amp;nbsp;&amp;nbsp;process to continue as quickly as possible.&amp;nbsp;&amp;nbsp;NOTE: Due to artifacts of the current implementation, the linger option no&amp;nbsp;&amp;nbsp;longer has an effect. It is still recognized by the system for backward&amp;nbsp;&amp;nbsp;compatibility. Currently, close operations complete as expeditiously as&amp;nbsp;&amp;nbsp;possible. If unsent data remains, the protocols will ensure its delivery. </description>
		<pubDate>Tue, 09 Aug 2011 22:33:32 +0800</pubDate>
	</item>
	<item>
		<title>EEPROM</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=6697</link>
		<description> </description>
		<pubDate>Tue, 09 Aug 2011 20:33:59 +0800</pubDate>
	</item>
	<item>
		<title>audio codec  驅動</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=6643</link>
		<description></description>
		<pubDate>Tue, 02 Aug 2011 20:05:06 +0800</pubDate>
	</item>
	<item>
		<title>Copy Protection IC</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=6341</link>
		<description></description>
		<pubDate>Sun, 10 Jul 2011 11:16:42 +0800</pubDate>
	</item>
	<item>
		<title>C 程式期中評量</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=6257</link>
		<description>&amp;nbsp;
&amp;nbsp;OpenBook </description>
		<pubDate>Thu, 30 Jun 2011 10:41:14 +0800</pubDate>
	</item>
	<item>
		<title>資料結構--graph</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=6190</link>
		<description>&amp;nbsp;
資料結構--graph 
BFS and DFS algorithm 
C 程式範例 </description>
		<pubDate>Wed, 22 Jun 2011 20:51:18 +0800</pubDate>
	</item>
	<item>
		<title>GPIO Interfaces in LINUX</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=5829</link>
		<description>GPIO Interfaces

This provides an overview of GPIO access conventions on Linux.

These calls use the gpio_* naming prefix.  No other calls should use that
prefix, or the related __gpio_* prefix.


What is a GPIO?
===============
A &quot;General Purpose Input/Output&quot; (GPIO) is a flexible software-controlled
digital signal.  They are provided from many kinds of chip, and are familiar
to Linux developers working with embedded and custom hardware.  Each GPIO
represents a bit connected to a particular pin, or &quot;ball&quot; on Ball Grid Array
(BGA) packages.  Board schematics show which external hardware connects to
which GPIOs.  Drivers can be written generically, so that board setup code
passes such pin configuration data to drivers.

System-on-Chip (SOC) processors heavily rely on GPIOs.  In some cases, every
non-dedicated pin can be configured as a GPIO; and most chips have at least
several dozen of them.  Programmable logic devices (like FPGAs) can easily
provide GPIOs; multifunction chips like power managers, and audio codecs
often have a few such pins to help with pin scarcity on SOCs; and there are
also &quot;GPIO Expander&quot; chips that connect using the I2C or SPI serial busses.
Most PC southbridges have a few dozen GPIO-capable pins (with only the BIOS
firmware knowing how they&#039;re used).

The exact capabilities of GPIOs vary between systems.  Common options:

  - Output values are writable (high=1, low=0).  Some chips also have
    options about how that value is driven, so that for example only one
    value might be driven ... supporting &quot;wire-OR&quot; and similar schemes
    for the other value (notably, &quot;open drain&quot; signaling).

  - Input values are likewise readable (1, 0).  Some chips support readback
    of pins configured as &quot;output&quot;, which is very useful in such &quot;wire-OR&quot;
    cases (to support bidirectional signaling).  GPIO controllers may have
    input de-glitch/debounce logic, sometimes with software controls.

  - Inputs can often be used as IRQ signals, often edge triggered but
    sometimes level triggered.  Such IRQs may be configurable as system
    wakeup events, to wake the system from a low power state.

  - Usually a GPIO will be configurable as either input or output, as needed
    by different product boards; single direction ones exist too.

  - Most GPIOs can be accessed while holding spinlocks, but those accessed
    through a serial bus normally can&#039;t.  Some systems support both types.

On a given board each GPIO is used for one specific purpose like monitoring
MMC/SD card insertion/removal, detecting card writeprotect status, driving
a LED, configuring a transceiver, bitbanging a serial bus, poking a hardware
watchdog, sensing a switch, and so on.


GPIO conventions
================
Note that this is called a &quot;convention&quot; because you don&#039;t need to do it this
way, and it&#039;s no crime if you don&#039;t.  There **are** cases where portability
is not the main issue; GPIOs are often used for the kind of board-specific
glue logic that may even change between board revisions, and can&#039;t ever be
used on a board that&#039;s wired differently.  Only least-common-denominator
functionality can be very portable.  Other features are platform-specific,
and that can be critical for glue logic.

Plus, this doesn&#039;t require any implementation framework, just an interface.
One platform might implement it as simple inline functions accessing chip
registers; another might implement it by delegating through abstractions
used for several very different kinds of GPIO controller.  (There is some
optional code supporting such an implementation strategy, described later
in this document, but drivers acting as clients to the GPIO interface must
not care how it&#039;s implemented.)

That said, if the convention is supported on their platform, drivers should
use it when possible.  Platforms must declare GENERIC_GPIO support in their
Kconfig (boolean true), and provide an &amp;lt;asm/gpio.h&amp;gt; file.  Drivers that can&#039;t
work without standard GPIO calls should have Kconfig entries which depend
on GENERIC_GPIO.  The GPIO calls are available, either as &quot;real code&quot; or as
optimized-away stubs, when drivers use the include file:

	#include &amp;lt;linux/gpio.h&amp;gt;

If you stick to this convention then it&#039;ll be easier for other developers to
see what your code is doing, and help maintain it.

Note that these operations include I/O barriers on platforms which need to
use them; drivers don&#039;t need to add them explicitly.


Identifying GPIOs
-----------------
GPIOs are identified by unsigned integers in the range 0..MAX_INT.  That
reserves &quot;negative&quot; numbers for other purposes like marking signals as
&quot;not available on this board&quot;, or indicating faults.  Code that doesn&#039;t
touch the underlying hardware treats these integers as opaque cookies.

Platforms define how they use those integers, and usually #define symbols
for the GPIO lines so that board-specific setup code directly corresponds
to the relevant schematics.  In contrast, drivers should only use GPIO
numbers passed to them from that setup code, using platform_data to hold
board-specific pin configuration data (along with other board specific
data they need).  That avoids portability problems.

So for example one platform uses numbers 32-159 for GPIOs; while another
uses numbers 0..63 with one set of GPIO controllers, 64-79 with another
type of GPIO controller, and on one particular board 80-95 with an FPGA.
The numbers need not be contiguous; either of those platforms could also
use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders.

If you want to initialize a structure with an invalid GPIO number, use
some negative number (perhaps &quot;-EINVAL&quot;); that will never be valid.  To
test if such number from such a structure could reference a GPIO, you
may use this predicate:

	int gpio_is_valid(int number);

A number that&#039;s not valid will be rejected by calls which may request
or free GPIOs (see below).  Other numbers may also be rejected; for
example, a number might be valid but temporarily unused on a given board.

Whether a platform supports multiple GPIO controllers is a platform-specific
implementation issue, as are whether that support can leave &quot;holes&quot; in the space
of GPIO numbers, and whether new controllers can be added at runtime.  Such issues
can affect things including whether adjacent GPIO numbers are both valid.

Using GPIOs
-----------
The first thing a system should do with a GPIO is allocate it, using
the gpio_request() call; see later.

One of the next things to do with a GPIO, often in board setup code when
setting up a platform_device using the GPIO, is mark its direction:

	/* set as input or output, returning 0 or negative errno */
	int gpio_direction_input(unsigned gpio);
	int gpio_direction_output(unsigned gpio, int value);

The return value is zero for success, else a negative errno.  It should
be checked, since the get/set calls don&#039;t have error returns and since
misconfiguration is possible.  You should normally issue these calls from
a task context.  However, for spinlock-safe GPIOs it&#039;s OK to use them
before tasking is enabled, as part of early board setup.

For output GPIOs, the value provided becomes the initial output value.
This helps avoid signal glitching during system startup.

For compatibility with legacy interfaces to GPIOs, setting the direction
of a GPIO implicitly requests that GPIO (see below) if it has not been
requested already.  That compatibility is being removed from the optional
gpiolib framework.

Setting the direction can fail if the GPIO number is invalid, or when
that particular GPIO can&#039;t be used in that mode.  It&#039;s generally a bad
idea to rely on boot firmware to have set the direction correctly, since
it probably wasn&#039;t validated to do more than boot Linux.  (Similarly,
that board setup code probably needs to multiplex that pin as a GPIO,
and configure pullups/pulldowns appropriately.)


Spinlock-Safe GPIO access
-------------------------
Most GPIO controllers can be accessed with memory read/write instructions.
Those don&#039;t need to sleep, and can safely be done from inside hard
(nonthreaded) IRQ handlers and similar contexts.

Use the following calls to access such GPIOs,
for which gpio_cansleep() will always return false (see below):

	/* GPIO INPUT:  return zero or nonzero */
	int gpio_get_value(unsigned gpio);

	/* GPIO OUTPUT */
	void gpio_set_value(unsigned gpio, int value);

The values are boolean, zero for low, nonzero for high.  When reading the
value of an output pin, the value returned should be what&#039;s seen on the
pin ... that won&#039;t always match the specified output value, because of
issues including open-drain signaling and output latencies.

The get/set calls have no error returns because &quot;invalid GPIO&quot; should have
been reported earlier from gpio_direction_*().  However, note that not all
platforms can read the value of output pins; those that can&#039;t should always
return zero.  Also, using these calls for GPIOs that can&#039;t safely be accessed
without sleeping (see below) is an error.

Platform-specific implementations are encouraged to optimize the two
calls to access the GPIO value in cases where the GPIO number (and for
output, value) are constant.  It&#039;s normal for them to need only a couple
of instructions in such cases (reading or writing a hardware register),
and not to need spinlocks.  Such optimized calls can make bitbanging
applications a lot more efficient (in both space and time) than spending
dozens of instructions on subroutine calls.


GPIO access that may sleep
--------------------------
Some GPIO controllers must be accessed using message based busses like I2C
or SPI.  Commands to read or write those GPIO values require waiting to
get to the head of a queue to transmit a command and get its response.
This requires sleeping, which can&#039;t be done from inside IRQ handlers.

Platforms that support this type of GPIO distinguish them from other GPIOs
by returning nonzero from this call (which requires a valid GPIO number,
which should have been previously allocated with gpio_request):

	int gpio_cansleep(unsigned gpio);

To access such GPIOs, a different set of accessors is defined:

	/* GPIO INPUT:  return zero or nonzero, might sleep */
	int gpio_get_value_cansleep(unsigned gpio);

	/* GPIO OUTPUT, might sleep */
	void gpio_set_value_cansleep(unsigned gpio, int value);


Accessing such GPIOs requires a context which may sleep,  for example
a threaded IRQ handler, and those accessors must be used instead of
spinlock-safe accessors without the cansleep() name suffix.

Other than the fact that these accessors might sleep, and will work
on GPIOs that can&#039;t be accessed from hardIRQ handlers, these calls act
the same as the spinlock-safe calls.

  ** IN ADDITION ** calls to setup and configure such GPIOs must be made
from contexts which may sleep, since they may need to access the GPIO
controller chip too:  (These setup calls are usually made from board
setup or driver probe/teardown code, so this is an easy constraint.)

	gpio_direction_input()
	gpio_direction_output()
	gpio_request()

## 	gpio_request_one()
##	gpio_request_array()
## 	gpio_free_array()

	gpio_free()
	gpio_set_debounce()



Claiming and Releasing GPIOs
----------------------------
To help catch system configuration errors, two calls are defined.

	/* request GPIO, returning 0 or negative errno.
	 * non-null labels may be useful for diagnostics.
	 */
	int gpio_request(unsigned gpio, const char *label);

	/* release previously-claimed GPIO */
	void gpio_free(unsigned gpio);

Passing invalid GPIO numbers to gpio_request() will fail, as will requesting
GPIOs that have already been claimed with that call.  The return value of
gpio_request() must be checked.  You should normally issue these calls from
a task context.  However, for spinlock-safe GPIOs it&#039;s OK to request GPIOs
before tasking is enabled, as part of early board setup.

These calls serve two basic purposes.  One is marking the signals which
are actually in use as GPIOs, for better diagnostics; systems may have
several hundred potential GPIOs, but often only a dozen are used on any
given board.  Another is to catch conflicts, identifying errors when
(a) two or more drivers wrongly think they have exclusive use of that
signal, or (b) something wrongly believes it&#039;s safe to remove drivers
needed to manage a signal that&#039;s in active use.  That is, requesting a
GPIO can serve as a kind of lock.

Some platforms may also use knowledge about what GPIOs are active for
power management, such as by powering down unused chip sectors and, more
easily, gating off unused clocks.

Note that requesting a GPIO does NOT cause it to be configured in any
way; it just marks that GPIO as in use.  Separate code must handle any
pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown).

Also note that it&#039;s your responsibility to have stopped using a GPIO
before you free it.

Considering in most cases GPIOs are actually configured right after they
are claimed, three additional calls are defined:

	/* request a single GPIO, with initial configuration specified by
	 * &#039;flags&#039;, identical to gpio_request() wrt other arguments and
	 * return value
	 */
	int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);

	/* request multiple GPIOs in a single call
	 */
	int gpio_request_array(struct gpio *array, size_t num);

	/* release multiple GPIOs in a single call
	 */
	void gpio_free_array(struct gpio *array, size_t num);

where &#039;flags&#039; is currently defined to specify the following properties:

	* GPIOF_DIR_IN		- to configure direction as input
	* GPIOF_DIR_OUT		- to configure direction as output

	* GPIOF_INIT_LOW	- as output, set initial level to LOW
	* GPIOF_INIT_HIGH	- as output, set initial level to HIGH

since GPIOF_INIT_* are only valid when configured as output, so group valid
combinations as:

	* GPIOF_IN		- configure as input
	* GPIOF_OUT_INIT_LOW	- configured as output, initial level LOW
	* GPIOF_OUT_INIT_HIGH	- configured as output, initial level HIGH

In the future, these flags can be extended to support more properties such
as open-drain status.

Further more, to ease the claim/release of multiple GPIOs, &#039;struct gpio&#039; is
introduced to encapsulate all three fields as:

	struct gpio {
		unsigned	gpio;
		unsigned long	flags;
		const char	*label;
	};

A typical example of usage:

	static struct gpio leds_gpios[] = {
		{ 32, GPIOF_OUT_INIT_HIGH, &quot;Power LED&quot; }, /* default to ON */
		{ 33, GPIOF_OUT_INIT_LOW,  &quot;Green LED&quot; }, /* default to OFF */
		{ 34, GPIOF_OUT_INIT_LOW,  &quot;Red LED&quot;   }, /* default to OFF */
		{ 35, GPIOF_OUT_INIT_LOW,  &quot;Blue LED&quot;  }, /* default to OFF */
		{ ... },
	};

	err = gpio_request_one(31, GPIOF_IN, &quot;Reset Button&quot;);
	if (err)
		...

	err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
	if (err)
		...

	gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));


GPIOs mapped to IRQs
--------------------
GPIO numbers are unsigned integers; so are IRQ numbers.  These make up
two logically distinct namespaces (GPIO 0 need not use IRQ 0).  You can
map between them using calls like:

	/* map GPIO numbers to IRQ numbers */
	int gpio_to_irq(unsigned gpio);

	/* map IRQ numbers to GPIO numbers (avoid using this) */
	int irq_to_gpio(unsigned irq);

Those return either the corresponding number in the other namespace, or
else a negative errno code if the mapping can&#039;t be done.  (For example,
some GPIOs can&#039;t be used as IRQs.)  It is an unchecked error to use a GPIO
number that wasn&#039;t set up as an input using gpio_direction_input(), or
to use an IRQ number that didn&#039;t originally come from gpio_to_irq().

These two mapping calls are expected to cost on the order of a single
addition or subtraction.  They&#039;re not allowed to sleep.

Non-error values returned from gpio_to_irq() can be passed to request_irq()
or free_irq().  They will often be stored into IRQ resources for platform
devices, by the board-specific initialization code.  Note that IRQ trigger
options are part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are
system wakeup capabilities.

Non-error values returned from irq_to_gpio() would most commonly be used
with gpio_get_value(), for example to initialize or update driver state
when the IRQ is edge-triggered.  Note that some platforms don&#039;t support
this reverse mapping, so you should avoid using it.


Emulating Open Drain Signals
----------------------------
Sometimes shared signals need to use &quot;open drain&quot; signaling, where only the
low signal level is actually driven.  (That term applies to CMOS transistors;
&quot;open collector&quot; is used for TTL.)  A pullup resistor causes the high signal
level.  This is sometimes called a &quot;wire-AND&quot;; or more practically, from the
negative logic (low=true) perspective this is a &quot;wire-OR&quot;.

One common example of an open drain signal is a shared active-low IRQ line.
Also, bidirectional data bus signals sometimes use open drain signals.

Some GPIO controllers directly support open drain outputs; many don&#039;t.  When
you need open drain signaling but your hardware doesn&#039;t directly support it,
there&#039;s a common idiom you can use to emulate it with any GPIO pin that can
be used as either an input or an output:

 LOW:	gpio_direction_output(gpio, 0) ... this drives the signal
	and overrides the pullup.

 HIGH:	gpio_direction_input(gpio) ... this turns off the output,
	so the pullup (or some other device) controls the signal.

If you are &quot;driving&quot; the signal high but gpio_get_value(gpio) reports a low
value (after the appropriate rise time passes), you know some other component
is driving the shared signal low.  That&#039;s not necessarily an error.  As one
common example, that&#039;s how I2C clocks are stretched:  a slave that needs a
slower clock delays the rising edge of SCK, and the I2C master adjusts its
signaling rate accordingly.


What do these conventions omit?
===============================
One of the biggest things these conventions omit is pin multiplexing, since
this is highly chip-specific and nonportable.  One platform might not need
explicit multiplexing; another might have just two options for use of any
given pin; another might have eight options per pin; another might be able
to route a given GPIO to any one of several pins.  (Yes, those examples all
come from systems that run Linux today.)

Related to multiplexing is configuration and enabling of the pullups or
pulldowns integrated on some platforms.  Not all platforms support them,
or support them in the same way; and any given board might use external
pullups (or pulldowns) so that the on-chip ones should not be used.
(When a circuit needs 5 kOhm, on-chip 100 kOhm resistors won&#039;t do.)
Likewise drive strength (2 mA vs 20 mA) and voltage (1.8V vs 3.3V) is a
platform-specific issue, as are models like (not) having a one-to-one
correspondence between configurable pins and GPIOs.

There are other system-specific mechanisms that are not specified here,
like the aforementioned options for input de-glitching and wire-OR output.
Hardware may support reading or writing GPIOs in gangs, but that&#039;s usually
configuration dependent:  for GPIOs sharing the same bank.  (GPIOs are
commonly grouped in banks of 16 or 32, with a given SOC having several such
banks.)  Some systems can trigger IRQs from output GPIOs, or read values
from pins not managed as GPIOs.  Code relying on such mechanisms will
necessarily be nonportable.

Dynamic definition of GPIOs is not currently standard; for example, as
a side effect of configuring an add-on board with some GPIO expanders.


GPIO implementor&#039;s framework (OPTIONAL)
=======================================
As noted earlier, there is an optional implementation framework making it
easier for platforms to support different kinds of GPIO controller using
the same programming interface.  This framework is called &quot;gpiolib&quot;.

As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file
will be found there.  That will list all the controllers registered through
this framework, and the state of the GPIOs currently in use.


Controller Drivers: gpio_chip
-----------------------------
In this framework each GPIO controller is packaged as a &quot;struct gpio_chip&quot;
with information common to each controller of that type:

 - methods to establish GPIO direction
 - methods used to access GPIO values
 - flag saying whether calls to its methods may sleep
 - optional debugfs dump method (showing extra state like pullup config)
 - label for diagnostics

There is also per-instance data, which may come from device.platform_data:
the number of its first GPIO, and how many GPIOs it exposes.

The code implementing a gpio_chip should support multiple instances of the
controller, possibly using the driver model.  That code will configure each
gpio_chip and issue gpiochip_add().  Removing a GPIO controller should be
rare; use gpiochip_remove() when it is unavoidable.

Most often a gpio_chip is part of an instance-specific structure with state
not exposed by the GPIO interfaces, such as addressing, power management,
and more.  Chips such as codecs will have complex non-GPIO state.

Any debugfs dump method should normally ignore signals which haven&#039;t been
requested as GPIOs.  They can use gpiochip_is_requested(), which returns
either NULL or the label associated with that GPIO when it was requested.


Platform Support
----------------
To support this framework, a platform&#039;s Kconfig will &quot;select&quot; either
ARCH_REQUIRE_GPIOLIB or ARCH_WANT_OPTIONAL_GPIOLIB
and arrange that its &amp;lt;asm/gpio.h&amp;gt; includes &amp;lt;asm-generic/gpio.h&amp;gt; and defines
three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep().

It may also provide a custom value for ARCH_NR_GPIOS, so that it better
reflects the number of GPIOs in actual use on that platform, without
wasting static table space.  (It should count both built-in/SoC GPIOs and
also ones on GPIO expanders.

ARCH_REQUIRE_GPIOLIB means that the gpiolib code will always get compiled
into the kernel on that architecture.

ARCH_WANT_OPTIONAL_GPIOLIB means the gpiolib code defaults to off and the user
can enable it and build it into the kernel optionally.

If neither of these options are selected, the platform does not support
GPIOs through GPIO-lib and the code cannot be enabled by the user.

Trivial implementations of those functions can directly use framework
code, which always dispatches through the gpio_chip:

  #define gpio_get_value	__gpio_get_value
  #define gpio_set_value	__gpio_set_value
  #define gpio_cansleep		__gpio_cansleep

Fancier implementations could instead define those as inline functions with
logic optimizing access to specific SOC-based GPIOs.  For example, if the
referenced GPIO is the constant &quot;12&quot;, getting or setting its value could
cost as little as two or three instructions, never sleeping.  When such an
optimization is not possible those calls must delegate to the framework
code, costing at least a few dozen instructions.  For bitbanged I/O, such
instruction savings can be significant.

For SOCs, platform-specific code defines and registers gpio_chip instances
for each bank of on-chip GPIOs.  Those GPIOs should be numbered/labeled to
match chip vendor documentation, and directly match board schematics.  They
may well start at zero and go up to a platform-specific limit.  Such GPIOs
are normally integrated into platform initialization to make them always be
available, from arch_initcall() or earlier; they can often serve as IRQs.


Board Support
-------------
For external GPIO controllers -- such as I2C or SPI expanders, ASICs, multi
function devices, FPGAs or CPLDs -- most often board-specific code handles
registering controller devices and ensures that their drivers know what GPIO
numbers to use with gpiochip_add().  Their numbers often start right after
platform-specific GPIOs.

For example, board setup code could create structures identifying the range
of GPIOs that chip will expose, and passes them to each GPIO expander chip
using platform_data.  Then the chip driver&#039;s probe() routine could pass that
data to gpiochip_add().

Initialization order can be important.  For example, when a device relies on
an I2C-based GPIO, its probe() routine should only be called after that GPIO
becomes available.  That may mean the device should not be registered until
calls for that GPIO can work.  One way to address such dependencies is for
such gpio_chip controllers to provide setup() and teardown() callbacks to
board specific code; those board specific callbacks would register devices
once all the necessary resources are available, and remove them later when
the GPIO controller device becomes unavailable.


Sysfs Interface for Userspace (OPTIONAL)
========================================
Platforms which use the &quot;gpiolib&quot; implementors framework may choose to
configure a sysfs user interface to GPIOs.  This is different from the
debugfs interface, since it provides control over GPIO direction and
value instead of just showing a gpio state summary.  Plus, it could be
present on production systems without debugging support.

Given appropriate hardware documentation for the system, userspace could
know for example that GPIO #23 controls the write protect line used to
protect boot loader segments in flash memory.  System upgrade procedures
may need to temporarily remove that protection, first importing a GPIO,
then changing its output state, then updating the code before re-enabling
the write protection.  In normal use, GPIO #23 would never be touched,
and the kernel would have no need to know about it.

Again depending on appropriate hardware documentation, on some systems
userspace GPIO can be used to determine system configuration data that
standard kernels won&#039;t know about.  And for some tasks, simple userspace
GPIO drivers could be all that the system really needs.

Note that standard kernel drivers exist for common &quot;LEDs and Buttons&quot;
GPIO tasks:  &quot;leds-gpio&quot; and &quot;gpio_keys&quot;, respectively.  Use those
instead of talking directly to the GPIOs; they integrate with kernel
frameworks better than your userspace code could.


Paths in Sysfs
--------------
There are three kinds of entry in /sys/class/gpio:

   -	Control interfaces used to get userspace control over GPIOs;

   -	GPIOs themselves; and

   -	GPIO controllers (&quot;gpio_chip&quot; instances).

That&#039;s in addition to standard files including the &quot;device&quot; symlink.

The control interfaces are write-only:

    /sys/class/gpio/

    	&quot;export&quot; ... Userspace may ask the kernel to export control of
		a GPIO to userspace by writing its number to this file.

		Example:  &quot;echo 19 &amp;gt; export&quot; will create a &quot;gpio19&quot; node
		for GPIO #19, if that&#039;s not requested by kernel code.

    	&quot;unexport&quot; ... Reverses the effect of exporting to userspace.

		Example:  &quot;echo 19 &amp;gt; unexport&quot; will remove a &quot;gpio19&quot;
		node exported using the &quot;export&quot; file.

GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
and have the following read/write attributes:

    /sys/class/gpio/gpioN/

	&quot;direction&quot; ... reads as either &quot;in&quot; or &quot;out&quot;.  This value may
		normally be written.  Writing as &quot;out&quot; defaults to
		initializing the value as low.  To ensure glitch free
		operation, values &quot;low&quot; and &quot;high&quot; may be written to
		configure the GPIO as an output with that initial value.

		Note that this attribute *will not exist* if the kernel
		doesn&#039;t support changing the direction of a GPIO, or
		it was exported by kernel code that didn&#039;t explicitly
		allow userspace to reconfigure this GPIO&#039;s direction.

	&quot;value&quot; ... reads as either 0 (low) or 1 (high).  If the GPIO
		is configured as an output, this value may be written;
		any nonzero value is treated as high.

		If the pin can be configured as interrupt-generating interrupt
		and if it has been configured to generate interrupts (see the
		description of &quot;edge&quot;), you can poll(2) on that file and
		poll(2) will return whenever the interrupt was triggered. If
		you use poll(2), set the events POLLPRI and POLLERR. If you
		use select(2), set the file descriptor in exceptfds. After
		poll(2) returns, either lseek(2) to the beginning of the sysfs
		file and read the new value or close the file and re-open it
		to read the value.

	&quot;edge&quot; ... reads as either &quot;none&quot;, &quot;rising&quot;, &quot;falling&quot;, or
		&quot;both&quot;. Write these strings to select the signal edge(s)
		that will make poll(2) on the &quot;value&quot; file return.

		This file exists only if the pin can be configured as an
		interrupt generating input pin.

	&quot;active_low&quot; ... reads as either 0 (false) or 1 (true).  Write
		any nonzero value to invert the value attribute both
		for reading and writing.  Existing and subsequent
		poll(2) support configuration via the edge attribute
		for &quot;rising&quot; and &quot;falling&quot; edges will follow this
		setting.

GPIO controllers have paths like /sys/class/gpio/gpiochip42/ (for the
controller implementing GPIOs starting at #42) and have the following
read-only attributes:

    /sys/class/gpio/gpiochipN/

    	&quot;base&quot; ... same as N, the first GPIO managed by this chip

    	&quot;label&quot; ... provided for diagnostics (not always unique)

    	&quot;ngpio&quot; ... how many GPIOs this manges (N to N + ngpio - 1)

Board documentation should in most cases cover what GPIOs are used for
what purposes.  However, those numbers are not always stable; GPIOs on
a daughtercard might be different depending on the base board being used,
or other cards in the stack.  In such cases, you may need to use the
gpiochip nodes (possibly in conjunction with schematics) to determine
the correct GPIO number to use for a given signal.


Exporting from Kernel code
--------------------------
Kernel code can explicitly manage exports of GPIOs which have already been
requested using gpio_request():

	/* export the GPIO to userspace */
	int gpio_export(unsigned gpio, bool direction_may_change);

	/* reverse gpio_export() */
	void gpio_unexport();

	/* create a sysfs link to an exported GPIO node */
	int gpio_export_link(struct device *dev, const char *name,
		unsigned gpio)

	/* change the polarity of a GPIO node in sysfs */
	int gpio_sysfs_set_active_low(unsigned gpio, int value);

After a kernel driver requests a GPIO, it may only be made available in
the sysfs interface by gpio_export().  The driver can control whether the
signal direction may change.  This helps drivers prevent userspace code
from accidentally clobbering important system state.

This explicit exporting can help with debugging (by making some kinds
of experiments easier), or can provide an always-there interface that&#039;s
suitable for documenting as part of a board support package.

After the GPIO has been exported, gpio_export_link() allows creating
symlinks from elsewhere in sysfs to the GPIO sysfs node.  Drivers can
use this to provide the interface under their own device in sysfs with
a descriptive name.

Drivers can use gpio_sysfs_set_active_low() to hide GPIO line polarity
differences between boards from user space.  This only affects the
sysfs interface.  Polarity change can be done both before and after
gpio_export(), and previously enabled poll(2) support for either
rising or falling edge will be reconfigured to follow this setting.
 </description>
		<pubDate>Sat, 14 May 2011 11:56:12 +0800</pubDate>
	</item>
	<item>
		<title>註冊中斷的流程</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=5828</link>
		<description>&amp;nbsp;
&amp;nbsp;註冊中斷的流程: 
&amp;nbsp;
step1:disable interrupt
step2:ack all interrupt
step3:register interrupt
step4: enable interrupt </description>
		<pubDate>Sat, 14 May 2011 11:30:59 +0800</pubDate>
	</item>
	<item>
		<title>File Format Specification</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=5768</link>
		<description>&amp;nbsp;
http://www.sonicspot.com/guide/midifiles.html
&amp;nbsp;
Standard MIDI files provide a common file format used by most musical software and hardware devices to store song information including the title, track names, and most importantly what instruments to use and the sequence of musical events, such as notes and instrument control information needed to play back the song. This standardization allows one software package to create and save files that can later be loaded and edited by another completely different program, even on a different type of computer. Almost every software music sequencer is capable of loading and saving standard MIDI files.
File Format Specification
Data FormatsAll data values are stored in Big-Endian (most significant byte first) format. Also, many values are stored in a variable-length format which may use one or more bytes per value. Variable-length values use the lower 7 bits of a byte for data and the top bit to signal a following data byte. If the top bit is set to 1, then another value byte follows. Below is a table of examples to help demonstrate how variable length values are used. 






Value

Variable-Length

Hex
Bin
Hex
Bin

00
00000000
00
00000000

C8
11001000
8148
10000001 01001000

100000
00010000 00000000 00000000
C08000
11000000 10000000 00000000Example values and their variable-length equivalents.
A variable-length value may use a maximum of 4 bytes. This means the maximum value that can be represented is 0x0FFFFFFF (represented as 0xFF, 0xFF, 0xFF, 0x7F). 
File StructureMIDI files are organized into data chunks (similar to RIFF files). Each chunk is prefixed with an 8 byte header: 4 byte ID string used to identify the type of chunk followed by a 4 byte size which defines the chunk&#039;s length as number of bytes following this chunk&#039;s header. 
Header ChunkThe header chunk contains information about the entire song including MIDI format type, number of tracks and timing division. There is only one header chunk per standard MIDI file and it always comes first. Before describing each element of the header chunk, here is a chart to help give an overview of the chunk&#039;s organization. 





Offset
Length
Type
Description
Value

0x00
4
char[4]
chunk ID
&quot;MThd&quot; (0x4D546864)

0x04
4
dword
chunk size
6 (0x00000006)

0x08
2
word
format type
0 - 2

0x10
2
word
number of tracks
1 - 65,535

0x12
2
word
time division
see following textMIDI Header Chunk Format 
Chunk ID and SizeThe chunk ID is always &quot;MThd&quot; (0x4D546864) and the size is always 6 because the header chunk always contains the same 3 word values. 
Format TypeThe first word describes the MIDI format type. It can be a value of 0, 1 or 2 and describes what how the following track information is to be interpreted. A type 0 MIDI file has one track that contains all of the MIDI events for the entire song, including the song title, time signature, tempo and music events. A type 1 MIDI file should have two or more tracks. The first, by convention, contains song information such as the title, time signature, tempo, etc. (more detail in Track Chunk section). The second and following tracks contain a title, musical event data, etc. specific to that track. This closely matches the organization of modern multi-track MIDI sequencers. A type 2 MIDI file is sort of a combination of the other two types. It contains multiple tracks, but each track represents a different sequence which may not necessarily be played simultaneously. This is meant to be used to save drum patterns, or other multi-pattern music sequences. 
Number of TracksThe second word simply defines the number of track chunks that follow this header chunk. A type 0 MIDI file may only contain a value of 1, because they can only contain one track. Type 1 and 2 MIDI files may contain up to 65,536 (0xFFFF) tracks. 
Time DivisionThe third and final word in the MIDI header chunk is a bit more complicated than the first two. It contains the time division used to decode the track event delta times into &quot;real&quot; time. This value is represents either ticks per beat or frames per second. If the top bit of the word (bit mask 0x8000) is 0, the following 15 bits describe the time division in ticks per beat. Otherwise the following 15 bits (bit mask 0x7FFF) describe the time division in frames per second. Ticks per beat translate to the number of clock ticks or track delta positions (described in the Track Chunk section) in every quarter note of music. Common values range from 48 to 960, although newer sequencers go far beyond this range to ease working with MIDI and digital audio together. Frames per second is defined by breaking the remaining 15 bytes into two values. The top 7 bits (bit mask 0x7F00) define a value for the number of SMPTE frames and can be 24, 25, 29 (for 29.97 fps) or 30. The remaining byte (bit mask 0x00FF) defines how many clock ticks or track delta positions there are per frame. So a time division example of 0x9978 could be broken down into it&#039;s three parts: the top bit is one, so it is in SMPTE frames per second format, the following 7 bits have a value of 25 (0x19) and the bottom byte has a value of 120 (0x78). This means the example plays at 24 frames per second SMPTE time and has 120 ticks per frame. 
Track ChunkTrack chunks contain all of the information for an individual track including, track name and music events. Here is an overview of a track chunk&#039;s organization. 





Offset
Length
Type
Description
Value

0x00
4
char[4]
chunk ID
&quot;MTrk&quot; (0x4D54726B)

0x04
4
dword
chunk size
see following text

0x08

track event data (see following text)MIDI Track Chunk Format 
Chunk ID and SizeThe chunk ID is always &quot;MTrk&quot; (0x4D54726B) and the size varies depending on the number of bytes used for all of the events contained in the track. 
Track Event DataThe track event data contains a stream of MIDI events that define information about the sequence and how it is played. The next section describes the different types of events. 
MIDI EventsTrack events are used to describe all of the musical content of a MIDI file, from tempo changes to sequence and track titles to individual music events. Each event includes a delta time, event type and usually some event type specific data. 
Delta-TimesThe event delta time is defined by a variable-length value. It determines when an event should be played relative to the track&#039;s last event. A delta time of 0 means that it should play simultaneously with the last event. A track&#039;s first event delta time defines the amount of time to wait before playing this first event. Events unaffected by time are still preceded by a delta time, but should always use a value of 0 and come first in the stream of track events. Examples of this type of event include track titles and copyright information. The most important thing to remember about delta times is that they are relative values, not absolute times. The actual time they represent is determined by a couple factors. The time division (defined in the MIDI header chunk) and the tempo (defined with a track event). If no tempo is define, 120 beats per minute is assumed. 
Types of EventsThere are three types of events: MIDI Control Events, System Exclusive Events and Meta Events. 
MIDI Channel EventsMusical control information such as playing a note or adjusting a MIDI channel&#039;s modulation value are defined by MIDI Channel Events. Each MIDI Channel Event consists of a variable-length delta time (like all track events) and a two or three byte description which determines the MIDI channel it corresponds to, the type of event it is and one or two event type specific values. Below is a table illustrating how MIDI Channel Events are formatted. 





Delta Time
Event Type Value
MIDI Channel
Parameter 1
Parameter 2

variable-length
4 bits
4 bits
1 byte
1 byteMIDI Channel Event Format 
MIDI Channel Events are the most common type of track event and usually make up the bulk of a MIDI file. The following table gives an overview of the seven MIDI Channel Events, listing their numeric value and parameters. 





Event Type
Value
Parameter 1
Parameter 2

Note Off
0x8
note number
velocity

Note On
0x9
note number
velocity

Note Aftertouch
0xA
note number
aftertouch value

Controller
0xB
controller number
controller value

Program Change
0xC
program number
not used

Channel Aftertouch
0xD
aftertouch value
not used

Pitch Bend
0xE
pitch value (LSB)
pitch value (MSB)MIDI Channel Events 
Although all of the MIDI Channel Events follow the same basic format, each one requires a bit of explanation. Below is a detailed description of each and how it is used. 




&amp;nbsp;

Note Off EventThe Note Off Event is used to signal when a MIDI key is released. These events have two parameters identical to a Note On event. The note number specifies which of the 128 MIDI keys is being played and the velocity determines how fast/hard the key was released. The note number is normally used to specify which previously pressed key is being released and the velocity is usually ignored, but is sometimes used to adjust the slope of an instrument&#039;s release phase. 





Note Off
MIDI Channel
Note Number
Velocity

8 (0x8)
0-15
0-127
0-127Note Off Event Value Ranges
Note On EventThe Note On Event is used to signal when a MIDI key is pressed. This type of event has two parameters. The note number that specifies which of the 128 MIDI keys is being played and the velocity determines how fast/hard the key is pressed. The note number is normally used to specify the instruments musical pitch and the velocity is usually used to specify the instruments playback volume and intensity. 





Note On
MIDI Channel
Note Number
Velocity

9 (0x9)
0-15
0-127
0-127Note On Event Value Ranges
Note Aftertouch Event The Note Aftertouch Event is used to indicate a pressure change on one of the currently pressed MIDI keys. It has two parameters. The note number of which key&#039;s pressure is changing and the aftertouch value which specifies amount of pressure being applied (0 = no pressure, 127 = full pressure). Note Aftertouch is used for extra expression of particular notes, often introducing or increasing some type of modulation during the instrument&#039;s sustain phase. 





Note Aftertouch
MIDI Channel
Note Number
Amount

10 (0xA)
0-15
0-127
0-127Note Aftertouch Event Value Ranges
Controller EventThe Controller Event signals the change in a MIDI channels state. There are 128 controllers which define different attributes of the channel including volume, pan, modulation, effects, and more. This event type has two parameters. The controller number specifies which control is changing and the controller value defines it&#039;s new setting. 





Controller
MIDI Channel
Controller Type
Value

11 (0xB)
0-15
0-127
0-127Controller Event Value Ranges
Below is a list of the defined MIDI controller types. 





Value
Controller Type

0 (0x00)
Bank Select

1 (0x01)
Modulation

2 (0x02)
Breath Controller

4 (0x04)
Foot Controller

5 (0x05)
Portamento Time

6 (0x06)
Data Entry (MSB)

7 (0x07)
Main Volume

8 (0x08)
Balance

10 (0x0A)
Pan

11 (0x0B)
Expression Controller

12 (0x0C)
Effect Control 1

13 (0x0D)
Effect Control 2

16-19 (0x10-0x13)
General-Purpose Controllers 1-4

32-63 (0x20-0x3F)
LSB for controllers 0-31

64 (0x40)
Damper pedal (sustain)

65 (0x41)
Portamento

66 (0x42)
Sostenuto

67 (0x43)
Soft Pedal

68 (0x44)
Legato Footswitch

69 (0x45)
Hold 2

70 (0x46)
Sound Controller 1 (default: Timber Variation)

71 (0x47)
Sound Controller 2 (default: Timber/Harmonic Content)

72 (0x48)
Sound Controller 3 (default: Release Time)

73 (0x49)
Sound Controller 4 (default: Attack Time)

74-79 (0x4A-0x4F)
Sound Controller 6-10

80-83 (0x50-0x53)
General-Purpose Controllers 5-8

84 (0x54)
Portamento Control

91 (0x5B)
Effects 1 Depth (formerly External Effects Depth)

92 (0x5C)
Effects 2 Depth (formerly Tremolo Depth)

93 (0x5D)
Effects 3 Depth (formerly Chorus Depth)

94 (0x5E)
Effects 4 Depth (formerly Celeste Detune)

95 (0x5F)
Effects 5 Depth (formerly Phaser Depth)

96 (0x60)
Data Increment

97 (0x61)
Data Decrement

98 (0x62)
Non-Registered Parameter Number (LSB)

99 (0x63)
Non-Registered Parameter Number (MSB)

100 (0x64)
Registered Parameter Number (LSB)

101 (0x65)
Registered Parameter Number (MSB)

121-127 (0x79-0x7F)
Mode MessagesDefined MIDI Controllers 
Program Change EventThe Program Change Event is used to change which program (instrument/patch) should be played on the MIDI channel. This type of event takes only one parameter, the program number of the new instrument/patch. 





Program Change
MIDI Channel
Program Number

12 (0xC)
0-15
0-127Program Change Event Value Ranges
Channel Aftertouch EventThe Channel Aftertouch Event is similar to the Note Aftertouch message, except it effects all keys currently pressed on the specific MIDI channel. This type of event takes only one parameter, the aftertouch amount (0 = no pressure, 127 = full pressure). 





Channel Aftertouch
MIDI Channel
Amount

13 (0xD)
0-15
0-127Channel Aftertouch Event Value Ranges
Pitch Bend EventThe Pitch Bend Event is similar to a controller event, except that it is a unique MIDI Channel Event that has two bytes to describe it&#039;s value. The pitch value is defined by both parameters of the MIDI Channel Event by joining them in the format of yyyyyyyxxxxxxx where the y characters represent the last 7 bits of the second parameter and the x characters represent the last 7 bits of the first parameter. The combining of both parameters enables high accuracy values (0 - 16383). The pitch value affects all playing notes on the current channel. Values below 8192 decrease the pitch, while values above 8192 increase the pitch. The pitch range may vary from instrument to instrument, but is usually +/-2 semi-tones. 





Pitch Bend
MIDI Channel
Value (LSB)
Value (MSB)

14 (0xE)
0-15
0-127
0-127Pitch Bend Event Value Ranges
Meta EventsEvents that are not to be sent or received over a MIDI port are called Meta Events. These events are defined by an event type value of 0xFF and have a variable size of parameter data which is defined after the event type. 





Meta Event
Type
Length
Data

255 (0xFF)
0-255
variable-length
type specificMeta Event Values
There are currently fifteen defined Meta Events. Each one is described in detail below. 




&amp;nbsp;

Sequence NumberThis meta event defines the pattern number of a Type 2 MIDI file or the number of a sequence in a Type 0 or Type 1 MIDI file. This meta event should always have a delta time of 0 and come before all MIDI Channel Events and non-zero delta time events. 





Meta Event
Type
Length
Number (MSB)
Number (LSB)

255 (0xFF)
0 (0x00)
2
0-255
0-255Sequence Number Meta Event Values
Text EventThis meta event defines some text which can be used for any reason including track notes, comments, etc. The text string is usually ASCII text, but may be any character (0x00-0xFF). 





Meta Event
Type
Length
Text

255 (0xFF)
1 (0x01)
string length
ASCII textText Meta Event Values
Copyright NoticeThis meta event defines copyright information including the copyright symbol &amp;copy; (0xA9), the year and the author. This meta event should always be in the first track chunk, have a delta time of 0 and come before all MIDI Channel Events and non-zero delta time events. 





Meta Event
Type
Length
Text

255 (0xFF)
2 (0x02)
string length
ASCII textCopyright Notice Meta Event Values
Sequence/Track NameThis meta event defines the name of a sequence when in a Type 0 or Type 2 MIDI file or in the first track of a Type 1 MIDI file. It defines a track name when it appears in any track after the first in a Type 1 MIDI file. This meta event should always have a delta time of 0 and come before all MIDI Channel Events and non-zero delta time events. 





Meta Event
Type
Length
Text

255 (0xFF)
3 (0x03)
string length
ASCII textSequence/Track Name Meta Event Values
Instrument NameThis meta event defines the name of an instrument being used in the current track chunk. This event can be used with the MIDI Channel Prefix meta event to define which instrument is being used on a specific channel. 





Meta Event
Type
Length
Text

255 (0xFF)
4 (0x04)
string length
ASCII textInstrument Name Meta Event Values
LyricsThis meta event defines the lyrics in a song and are usually used to define a syllable or group of works per quarter note. This event can be used as an equivalent of sheet music lyrics or for implementing a karaoke-style system. 





Meta Event
Type
Length
Text

255 (0xFF)
5 (0x05)
string length
ASCII textLyrics Meta Event Values
MarkerThis meta event marks a significant point in time for the sequence. It is usually found in the first track chunk, but may appear in any one. This event can be useful for marking the beginning/end of a new verse or chorus. 





Meta Event
Type
Length
Text

255 (0xFF)
6 (0x06)
string length
ASCII textMarker Meta Event Values
Cue PointThis meta event marks the start of some type of new sound or action. It is usually found in the first track chunk, but may appear in any one. This event is sometimes used by sequencers to mark when playback of a sample or video should begin. 





Meta Event
Type
Length
Text

255 (0xFF)
7 (0x07)
string length
ASCII textCue Point Meta Event Values
MIDI Channel PrefixThis meta event associates a MIDI channel with following meta events. It&#039;s effect is terminated by another MIDI Channel Prefix event or any non- Meta event. It is often used before an Instrument Name Event to specify which channel an instrument name represents. 





Meta Event
Type
Length
Channel

255 (0xFF)
32 (0x20)
1
0-15MIDI Channel Prefix Meta Event Values
End Of TrackThis meta event is used to signal the end of a track chunk and must always appear as the last event in every track chunk. 





Meta Event
Type
Length

255 (0xFF)
47 (0x2F)
0End Of Track Meta Event Values
Set TempoThis meta event sets the sequence tempo in terms of microseconds per quarter-note which is encoded in three bytes. It usually is found in the first track chunk, time-aligned to occur at the same time as a MIDI clock message to promote more accurate synchronization. If no set tempo event is present, 120 beats per minute is assumed. The following formula&#039;s can be used to translate the tempo from microseconds per quarter-note to beats per minute and back. 
MICROSECONDS_PER_MINUTE = 60000000BPM = MICROSECONDS_PER_MINUTE / MPQNMPQN = MICROSECONDS_PER_MINUTE / BPM





Meta Event
Type
Length
Microseconds/Quarter-Note

255 (0xFF)
81 (0x51)
3
0-8355711Set Tempo Meta Event Values
SMPTE OffsetThis meta event is used to specify the SMPTE starting point offset from the beginning of the track. It is defined in terms of hours, minutes, seconds, frames and sub-frames (always 100 sub-frames per frame, no matter what sub-division is specified in the MIDI header chunk). The byte used to specify the hour offset also specifies the frame rate in the following format: 0rrhhhhhh where rr is two bits for the frame rate where 00=24 fps, 01=25 fps, 10=30 fps (drop frame), 11=30 fps and hhhhhh is six bits for the hour (0-23). The hour byte&#039;s top bit is always 0. The frame byte&#039;s possible range depends on the encoded frame rate in the hour byte. A 25 fps frame rate means that a maximum value of 24 may be set for the frame byte. 





Meta Event
Type
Length
Hour
Min
Sec
Fr
SubFr

255 (0xFF)
84 (0x54)
5
0-23 *
0-59
0-59
0-30 *
0-99SMPTE Offset Meta Event Values, * read preceding text for details
Time SignatureThis meta event is used to set a sequences time signature. The time signature defined with 4 bytes, a numerator, a denominator, a metronome pulse and number of 32nd notes per MIDI quarter-note. The numerator is specified as a literal value, but the denominator is specified as (get ready) the value to which the power of 2 must be raised to equal the number of subdivisions per whole note. For example, a value of 0 means a whole note because 2 to the power of 0 is 1 (whole note), a value of 1 means a half-note because 2 to the power of 1 is 2 (half-note), and so on. The metronome pulse specifies how often the metronome should click in terms of the number of clock signals per click, which come at a rate of 24 per quarter-note. For example, a value of 24 would mean to click once every quarter-note (beat) and a value of 48 would mean to click once every half-note (2 beats). And finally, the fourth byte specifies the number of 32nd notes per 24 MIDI clock signals. This value is usually 8 because there are usually 8 32nd notes in a quarter-note. At least one Time Signature Event should appear in the first track chunk (or all track chunks in a Type 2 file) before any non-zero delta time events. If one is not specified 4/4, 24, 8 should be assumed. 





Meta Event
Type
Length
Numer
Denom
Metro
32nds

255 (0xFF)
88 (0x58)
4
0-255
0-255
0-255
1-255Time Signature Meta Event Values
Key SignatureThis meta event is used to specify the key (number of sharps or flats) and scale (major or minor) of a sequence. A positive value for the key specifies the number of sharps and a negative value specifies the number of flats. A value of 0 for the scale specifies a major key and a value of 1 specifies a minor key. 





Meta Event
Type
Length
Key
Scale

255 (0xFF)
89 (0x59)
2
-7-7
0-1Key Signature Meta Event Values
Sequencer SpecificThis meta event is used to specify information specific to a hardware or software sequencer. The first Data byte (or three bytes if the first byte is 0) specifies the manufacturer&#039;s ID and the following bytes contain information specified by the manufacturer. The individual manufacturers may document this information in their respective manuals. 





Meta Event
Type
Length
Data

255 (0xFF)
127 (0x7F)
variable-length
any type and amount *Sequencer Specific Meta Event Values, * read preceding text for details
System Exclusive EventsAlso known as SysEx Events, these MIDI events are used to control MIDI hardware or software that require special data bytes that will follow their manufacturer&#039;s specifications. Every SysEx event includes an ID that specifies which manufacturer&#039;s product is to be the intended receiver (see the MIDI Manufacturers List). All other products will ignore the event. There are three types of SysEx messages which are used to send data in a single event, across multiple events or authorize the transmission of specific MIDI messages. 




&amp;nbsp;

Normal SysEx EventsThese are the most common type of SysEx event and are used to hold a single block of manufacturer specific data. The first byte is always 0xF0 and the second is a variable-length value that specifies the length of the following SysEx data in bytes. The SysEx data bytes must always end with a 0xF7 byte to signal the end of the message. 





SysEx Event
Length
Data

240 (0xF0)
variable-length
data bytes, 0xF7Normal SysEx Event Values
Divided SysEx EventsA large amount of SysEx data in a Normal SysEx Event could cause following MIDI Channel Events to be transmitted after the time they should be played. This will cause an unwanted delay in play back of the following events. The second type of SysEx Events solve this problem by allowing a large amount of SysEx data to be divided into smaller blocks, transmitted with a delay between each division to allow the transmission of other MIDI events in order to prevent congesting of the limited MIDI bandwidth. The initial Divided SysEx Event follows the same format as a Normal SysEx Event with the exception that the last data byte is not 0xF7. This indicates the the SysEx data is not finished and will be continued in an upcoming Divided SysEx Event. Any following Divided SysEx Events before the final one use the a similar format as the first, only the start byte is 0xF0 instead of 0xF7 to signal continuation of SysEx data. The final block follows the same format as the continuation blocks, except the last data byte is 0xF7 to signal the completion of the divided SysEx data. 





SysEx Event
Length
Data

240 (0xF0)
variable-length
data bytes

247 (0xF7)
variable-length
data bytes

247 (0xF7)
variable-length
data bytes, 0xF7Divided SysEx Event Values
Authorization SysEx EventsThe last type of SysEx Event authorizes and enables the transmission of special messages such as Song Position Pointer, MIDI Time Code and Song Select messages. These SysEx Events use the event type value 0xF7. 





SysEx Event
Length
Data

247 (0xF7)
variable-length
data bytesAuthorization SysEx Event Values </description>
		<pubDate>Sat, 07 May 2011 00:58:28 +0800</pubDate>
	</item>
	<item>
		<title>紅外線電路圖</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=5692</link>
		<description>&amp;nbsp;
&amp;nbsp; 請參考,可以先用我的去測試, OK後 , 
&amp;nbsp;&amp;nbsp;請自己銲一個...
&amp;nbsp; 相關軟體 請參考LIRC 
&amp;nbsp;
相關 DataSheet 如附件
&amp;nbsp; 
&amp;nbsp;
&amp;nbsp;
&amp;nbsp; </description>
		<pubDate>Sat, 30 Apr 2011 11:57:22 +0800</pubDate>
	</item>
	<item>
		<title>mdev – mini udev in busybox</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=5516</link>
		<description>http://wildanm.wordpress.com/2007/08/21/mdev-mini-udev-in-busybox/
mdev – mini udev in&amp;nbsp;busybox




When recompile busybox for my ngw board, there is interesting option : mdev, on previous post we saw that openwrt offer hotplug2 for udev replacement, altough openwrt use busybox also ….




The following is the doc related to mdev&amp;nbsp; which i get from busybox 1.6.1 distribution :
————-MDEV Primer————-
For those of us who know how to use mdev, a primer might seem lame.&amp;nbsp; Foreveryone else, mdev is a weird black box that they hear is awesome, but can’tseem to get their head around how it works.&amp;nbsp; Thus, a primer.
———–Basic Use———–
Mdev has two primary uses: initial population and dynamic updates.&amp;nbsp; Bothrequire sysfs support in the kernel and have it mounted at /sys.&amp;nbsp; For dynamicupdates, you also need to have hotplugging enabled in your kernel.
Here’s a typical code snippet from the init script:[1] mount -t sysfs sysfs /sys[2] echo /bin/mdev &amp;gt; /proc/sys/kernel/hotplug[3] mdev -s
Of course, a more “full” setup would entail executing this before the previouscode snippet:[4] mount -t tmpfs mdev /dev[5] mkdir /dev/pts[6] mount -t devpts devpts /dev/pts
The simple explanation here is that [1] you need to have /sys mounted beforeexecuting mdev.&amp;nbsp; Then you [2] instruct the kernel to execute /bin/mdev whenevera device is added or removed so that the device node can be created ordestroyed.&amp;nbsp; Then you [3] seed /dev with all the device nodes that were createdwhile the system was booting.
For the “full” setup, you want to [4] make sure /dev is a tmpfs filesystem(assuming you’re running out of flash).&amp;nbsp; Then you want to [5] create the/dev/pts mount point and finally [6] mount the devpts filesystem on it.
————-MDEV Config&amp;nbsp;&amp;nbsp; (/etc/mdev.conf)————-
Mdev has an optional config file for controlling ownership/permissions ofdevice nodes if your system needs something more than the default root/root660 permissions.
The file has the format:&amp;lt;device regex&amp;gt; &amp;lt;uid&amp;gt;:&amp;lt;gid&amp;gt; &amp;lt;octal permissions&amp;gt;For example:hd[a-z][0-9]* 0:3 660
The config file parsing stops at the first matching line.&amp;nbsp; If no line ismatched, then the default of 0:0 660 is used.&amp;nbsp; To set your own default, simplycreate your own total match like so:.* 1:1 777
If you also enable support for executing your own commands, then the file hasthe format:&amp;lt;device regex&amp;gt; &amp;lt;uid&amp;gt;:&amp;lt;gid&amp;gt; &amp;lt;octal permissions&amp;gt; [&amp;lt;@|$|*&amp;gt; &amp;lt;command&amp;gt;]The special characters have the meaning:@ Run after creating the device.$ Run before removing the device.* Run both after creating and before removing the device.
The command is executed via the system() function (which means you’re giving acommand to the shell), so make sure you have a shell installed at /bin/sh.
For your convenience, the shell env var $MDEV is set to the device name.&amp;nbsp; So ifthe device ‘hdc’ was matched, MDEV would be set to “hdc”. </description>
		<pubDate>Sat, 16 Apr 2011 15:46:13 +0800</pubDate>
	</item>
	<item>
		<title>[轉貼] SVN 指令</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=5433</link>
		<description>
&amp;nbsp;


先來看 SVN Trunk/Tags/Branches 目錄 的 架構 和 用途:(英文說明轉載自 SubTrain PPT) 

trunk: Main line of development(主幹, 主要開發都由在 trunk) 
tags: Releases (想要 Release 的時後, 就標個 Tag, 以後可以依 Tag 來找回之前版本的資料) 
branches: Preparation of release, bug fixing(分支, 可以將某些功能切出來, 或者 bug fix 等切成分支, 等做完後再用 Merge 合併回來) 
SVN 基本功能: 
Import: 將整個 project_directory 的資料 import 進 svn 裡面 

svn import project_directory http://DOMAIN/svn_project 
svn import project_directory file:///SVN_PATH/svn_project 
Checkout: (checkout 可簡寫成 co), 將資料 checkout 回來 

svn co http://SVN_PATH/svn_project 
svn co file:///SVN_PATH/svn_project 
svn co -r 12 file:///var/lib/svn/dev/projects # 出第12版的 projcets code
List: (list 可簡寫成 ls), 看上面有哪些檔案/資料 

svn ls http://SVN_PATH/svn_project 
svn ls file:///SVN_PATH/svn_project 
Update: (update 可簡寫成 up), 將目前資訊更新成 SVN 線上最新版本. 

SVN_CHECKOUT_DIR$ svn up 
Commit: (commit 可簡寫成 ci), 將目前所做的修改 commit 回 svn

SVN_CHECKOUT_DIR$ svn ci
Status: (status 可簡寫成 st), 看目前檔案/結構 跟 SVN 線上的版本有哪些不同

SVN_CHECKOUT_DIR$ svn st
Add: 將此 檔案/目錄 新增進 svn

SVN_CHECKOUT_DIR$ svn add filename 或 svn add directory
MV: 改檔名, 並且此檔案之前紀錄還要繼續留下

SVN_CHECKOUT_DIR$ svn mv filename new_filename
Revert: 還原這次的修改, 回到前一版的檔案狀態(未 commit 前可用)

SVN_CHECKOUT_DIR$&amp;nbsp; svn revert [file | directory]
SVN 檔案狀態資訊: 

?: 此檔案不存在 SVN 裡面 
A: 此次新增的檔案 
C: 此檔案已經有人改過, 合併不成功, 需要人工介入 
D: 此次移除的檔案 
M: 此檔案有修改過 
U: 此檔案有被更新過
再來是比較進階一點點, 下述範例轉載自 SubTrain 的教學 PPT: 
建立一個 branch 

svn copy http://svnserver/calc/trunk http://svnserver/calc/branches/my-calc-branch -m ‘create a branch’&amp;nbsp;
建立 Release Tags: 

svn copy http://svnserver/calc/trunk http://svnserver/calc/tags/Release-1.0.0 -m ‘create Release tags for Release 1.0.0′
合併兩個版本的檔案 # 參考自: 用 Subversion 的 Merge 來 Undo 

svn merge -r REV1:REV2 {path/to/workingcopy} 
&amp;nbsp;(UNDO) svn merge -r 1234:1233 … 
&amp;nbsp;(MERGE)svn merge -r 1233:1234 … 
svn merge –dry-run -r 343:344 http://svn.example.com/repos/calc/trunk
有 &quot;C&quot; 狀態處理完後, 用 resolved&amp;nbsp; 將自動產生的檔案刪除, 才能正常 commit: 

svn resolved filename # 這樣子下就會把自動產生 diff 等的檔案刪除
找版本間有什麼不同 diff: 

svn diff # 自動以現在檔案跟 SVN 內最新版做 diff 
svn diff -r9237:9238 
Info: 列出現在路徑, 版本編號, 最後一次修改日期 … 等資訊 

svn info
Log: 如果沒輸入參數, 預設會把所有 commit log 都列出來 

svn log 
svn log -l 10 # 顯示 10 筆(最新 10筆 Log) 
svn log -c 100 # 顯示 revision 100 的 Log 
svn log -v -c 100 # 顯示&amp;nbsp; revision 100 的詳細 Log
Propset (propset, pset, ps): 版本控制都有些特殊 Keyword 設定, 如 Id 就是最常用的, 設定方法如下: 

在檔案內找地方加入 $Id$ 
設定此檔案要能吃 Id 的 Keyword: svn ps svn:keywords ‘Id’ filename (只需設一次即可, 之後就不用再設) 
svn ci 後, $Id$ 會自動代換成 $Id:filename 編號 年月日時分秒 username $ 的資訊 
svn help ps 可以看到有哪些 Keyword 可以用, 即 Keyword 的說明.(ex: URL, Author, Date, Rev, Id 等.)
來源: 
http://blog.longwin.com.tw/2007/07/svn_tutorial_2007/
Tsung&#039;s Blog 
個人筆記, 記錄關於 系統、程式、新聞 與 日常生活 等資訊
Subversion 版本控制系統
&amp;nbsp; </description>
		<pubDate>Mon, 11 Apr 2011 12:12:14 +0800</pubDate>
	</item>
	<item>
		<title>Qt for Embedded Linux Display</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=5305</link>
		<description>Qt for Embedded Linux Display Management
&amp;nbsp;
When rendering, the default behavior for each Qt for Embedded Linux client is to render its widgets into memory, while the server is responsible for putting the contents of the memory onto the screen. The server uses the screen driver to copy the content of the memory to the display.
The screen driver is loaded by the server application when it starts running, using Qt&#039;s plugin system.
Contents:



Available Drivers

Specifying a Driver

Subdrivers and Multiple Drivers
&amp;nbsp;
Available Drivers
Qt for Embedded Linux provides drivers for the Linux framebuffer, the virtual framebuffer, transformed screens, VNC servers and multi screens. Run the configure script to list the available drivers:
./configure -help
In the default Qt configuration, only an unaccelerated Linux framebuffer driver (/dev/fb0) is enabled. The various drivers can be enabled and disabled using the configure script. For example:
./configure -qt-gfx-transformed
Custom screen drivers can be implemented by subclassing the QScreen class and creating a screen driver plugin (derived from the QScreenDriverPlugin class). The default implementation of the QScreenDriverFactory class will automatically detect the plugin, loading the driver into the server application at run-time.
&amp;nbsp;
Specifying a Driver
To specify which driver to use, set the QWS_DISPLAY environment variable. For example (if the current shell is bash, ksh, zsh or sh):
export QWS_DISPLAY=&quot;&amp;lt;driver&amp;gt;[:&amp;lt;driver specific options&amp;gt;]... [:&amp;lt;display num&amp;gt;]&quot;
The valid values for the &amp;lt;driver&amp;gt; argument are LinuxFb, QVFb, VNC, Transformed, Multi and keys identifying custom drivers, and the &amp;lt;display num&amp;gt; argument is used to separate screens that are using the same screen driver and to enable multiple displays (see the Running Qt for Embedded Linux Applications documentation for more details). The driver specific options are described in the table below.
&amp;nbsp;




Driver Specific Option

Available For

Description



tty=&amp;lt;device&amp;gt;

LinuxFb

Passes the device file to the console the application is running on.


nographicsmodeswitch

LinuxFb

Ensures that the application is not in graphics mode.


littleendian

LinuxFb

Tells the driver it must handle a little-endian frame buffer in a big-endian system.


mmWidth=&amp;lt;value&amp;gt; 

LinuxFb, QVFb

The screen&#039;s physical width (used to calculate DPI).


mmHeight=&amp;lt;value&amp;gt; 

LinuxFb, QVFb

The screen&#039;s physical height (used to calculate DPI).


&amp;lt;device&amp;gt;

LinuxFb

&amp;nbsp;


&amp;lt;subdriver&amp;gt;

VNC, Transformed, Multi

Specifies a subdriver.


&amp;lt;RotX&amp;gt;

Transformed

Specifies the rotation of the screen. The valid values of X are 90, 180 and 270.


offset=&amp;lt;x,y&amp;gt;

Multi

Specifies the coordinates of a subscreen&#039;s top-left corner (by default 0,0).
&amp;nbsp;
The QWS_DISPLAY environment variable can also be set using the -display option when running an application. For example:
myApplication -display &quot;&amp;lt;driver&amp;gt;[:&amp;lt;driver specific options&amp;gt;]... [:&amp;lt;display num&amp;gt;]&quot;
&amp;nbsp;
Subdrivers and Multiple Drivers
The VNC, Transformed and Multi screen drivers depend on subdrivers. The general syntax for specifying a driver is as follows:
export QWS_DISPLAY=&quot;&amp;lt;driver&amp;gt;[:&amp;lt;subdriver&amp;gt;][:&amp;lt;subdriver options&amp;gt;]... [ :&amp;lt;display num&amp;gt;]&quot;
In the case of subdrivers, it is important to add a space between each subdriver and before the display number to separate the various drivers and displays. Note that Multi screen drivers can have several subdrivers. For example:
export QWS_DISPLAY=&quot;Multi: QVFb:0 QVFb:offset=640,0:1 :2&quot;
Note also that the VNC screen driver defaults to a virtual screen driver if no subdriver is specified. In this case the VNC driver accepts a few additional (optional) arguments specifying the size and depth of the default virtual screen:


size=&amp;lt;width x height&amp;gt;

depth=&amp;lt;value&amp;gt;

mmHeight=&amp;lt;physical height in millimeters&amp;gt;

mmWidth=&amp;lt;physical width in millimeters&amp;gt;
Example running the VNC screen driver with a virtual screen of size 720x480 with 32 bits per pixel:
export QWS_DISPLAY=&quot;VNC:size=720x480:depth=32&quot;
Example running the VNC screen driver on top of the Linux framebuffer driver:
export QWS_DISPLAY=&quot;VNC:LinuxFb&quot;
In this last example, Qt is using two screen drivers simultaneously, displaying output on both the device&#039;s screen and across a network on VNC client displays.
&amp;nbsp;








Copyright &amp;copy; 2010 Nokia Corporation and/or its 
&amp;nbsp;http://doc.qt.nokia.com/4.6/qt-embedded-displaymanagement.html </description>
		<pubDate>Mon, 28 Mar 2011 19:19:34 +0800</pubDate>
	</item>
	<item>
		<title>C程式設計作業--for 就業班同學</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=5149</link>
		<description>&amp;nbsp;
C程式設計作業 --- 簡單訂位系統
&amp;nbsp;
The Colossus Airlines fleet consists of one plane with a seating capacity of 30. It makes one flight daily. Write a seating reservation program with the following features:


The program uses linked list. Each structure should hold a seat identification number, a marker that indicates whether the seat is assigned, the last name of the seat holder, and the first name of the seat holder. 
The program displays the following menu:
To choose a function, enter its letter label:
a) Show number of empty seats
b) Show list of empty seats
c) Show alphabetical list of seats (sorting)
d) Assign a customer to a seat assignment
e) Delete a seat assignment
f) Quit


The program successfully executes the promises of its menu. Choices d) and e) require additional input, and each should enable the user to abort entry. 
After executing a particular function, the program shows the menu again, except for choice f). 
Data is saved in a file between runs. When the program is restarted, it first loads in the data, if any, from the file.(file I/O)
[註]: 
1.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 須使用C 語言
2.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;有限時間內極盡可能地以物件導向的思維來撰寫 (功能正確50%, 軟體架構50%)
3.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 使用 struct 定義person, seat, 系統操作以function pointer來實現show, assign,delete,sort.等操作.
&amp;nbsp; </description>
		<pubDate>Wed, 16 Mar 2011 17:14:46 +0800</pubDate>
	</item>
	<item>
		<title>技術文章：如何撰寫 Linux PCI BUS I驅動程式</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=4598</link>
		<description>





因應系統主控制器　PCI驅動程式撰寫大不同
&amp;nbsp;


2011/2&amp;nbsp;&amp;nbsp;Victor (本文作者為艾鍗學院講師)









PCI是一種可以擴充周邊元件的匯流排，在個人電腦上非常普遍，為一個共同的標準介面，可以讓很多的周邊元件附加在個人電腦上，雖然現在的嵌入式系統已經把很多的周邊系統做成系統單晶片(SoC)的中央處理器，但有時候在成本的考量下，PCI可以選擇所要擴充的周邊，避免SoC的中央處理器(CPU)成本過高，十分具有優勢。另外，把過多的周邊元件做成SoC，會造成CPU用電過高，更進而造成過高的溫度，必須使用其他的散熱元件，如鋁片或風扇等，反而造成產品體積變大並增加成本。





PCI的另一個好處是隨插即用(PNP)，對資源的分配及取得也具有相當大的彈性，如此一來，軟體撰寫者也可受惠，除軟體較容易移植至不同的CPU平台外，也不須遷就不同的CPU而撰寫不同的程式。 &amp;nbsp; 
ARM控制器製造商多　PCI軟體須分別撰寫&amp;nbsp; 
以硬體來說，PCI不同處在於它本身是一個高速傳輸標準；至於在軟體方面，因為x86只有一種CPU，其PCI主端控制晶片都一樣，並不會因為不同的生產廠商有所不同，因此在PCI主端的驅動程式都由作業系統廠商撰寫，但是採用安謀國際(ARM)所生產的PCI主端控制器都不同，所以軟體人員必須各別撰寫，以應付不同的中央處理器，故必須了解如何撰寫PCI主端驅動程式(圖1)。 &amp;nbsp; 







圖1 不同於x86的PCI主控端晶片，ARM架構的控制器種類繁多。
此外，PCI採取主從式架構，主端(Host)由主機板廠商負責，以x86平台而言，通常會留下幾個標準的擴充槽，讓使用者購買其他從端(Client)的擴充卡增加周邊元件，在以ARM為基礎的嵌入系統中，PCI主端會是在CPU內的SoC，對於從端的元件，原則上不會做成插卡式的擴充槽，通常是直接將PCI匯流排的訊號線從PCI主端連接至PCI從端，如此一來就可以節省空間及成本。 &amp;nbsp; 
PCI逐一分配周邊元件資源&amp;nbsp; 
在開機程序中，開機時PCI主端會先初始化自我控制器，之後再將可分配及使用的資源和系統登錄，掃描是否有任何PCI從端的周邊元件連線上系統，一旦確認連線後，PCI主端則依照要求分配資源給其他周邊元件。分配結束之後，PCI主端須檢查是否有相對應的從端登錄驅動程式，以呼叫其所登錄的Call Back Function，Call Back Function則由PCI從端的驅動程式登錄，在Call Back Function中通常會完成元件初始化，PCI主端將會逐一針對連結上的PCI從端執行重覆的動作，直到完成所有周邊元件的資源分配。 &amp;nbsp; 
擔任主/從端橋梁　結構表擔任資源交換依據&amp;nbsp; 
在PCI主端和PCI從端之間存在結構表(Configuration Table)，該表具有二百五十六字元，並作為主端和從端之間溝通資源分配及資訊交換的依據(圖2)，此表存放在PCI從端上，其中Vendor ID &amp;amp; Device ID屬於唯讀，並交由PCI主端儲存。PCI從端也是用這兩個ID向主端註冊，PCI主端也會依照此ID進行比對，當前面所提要呼叫從端時，才知道呼叫的驅動程式。PCI主端要求從端所執行的動作稱為指令，這些指令在PCI的標準受到定義。狀態是目前從端現狀的表示，也在PCI標準中有所定義。 &amp;nbsp; 







圖2 結構表
另外，非常重要的項目還包括Base Address Registers，它主要是用來描述PCI從端和主端的資源，而且它是一個可以雙向溝通的資料，對32位元的設備而言，總共最多有六個資源可以取得；若是64位元的設備，則最多只有三個資源可以取得，其實作法很簡單，就是將兩個32位元合成一個64位元。 &amp;nbsp; 
在此僅針對32位元的設備進行說明，因為目前64位元的嵌入式並不多見，在說明之前必須了解，當CPU和周邊進行溝通可以從有兩個路徑著手，分別為輸入/輸出(I/O)存取及記憶體存取。由於硬體有所差異，所以必須透過欄位使用最低的兩個位元，以表示需要的資源。以二進位來看，00代表需要記憶，01代表需要I/O，所要求的大小從位元2開始，若不需要則以零作為表示，不然則填上需要的數值大小，當PCI主端掃描之後，會填上從端周邊所分配到的起始位置，才完成資源的分配。 &amp;nbsp; 
毋須改變硬體架構　PCI主端僅改寫HAL&amp;nbsp; 
在了解PCI匯流排的基本定義之後，接著必須了解實作部分。在PCI主端方面，因為前面所提的部分標準和硬體無關，或者可以說，硬體工作內容一樣，因為這部分已由GNU&#039;s Not Unix(GNU)撰寫完成，不須進行任何更動。這部分的原始碼在核心原始碼(Kernel Source)的drivers/pci目錄之下，使用者所要寫的是硬體抽象(HAL)層部分，必須在arch/arm/mach-xxxx的目錄之下，這個目錄是使用者移植(Porting)SoC時建立的目錄，其中的xxxx是使用者自行定義的名稱)，撰寫一個PCI主端的一個C程式，而在這程式有幾個部分須要撰寫，首先須要宣告一個資料結構如下： &amp;nbsp; 
struct hw_pci ixdp425_pci __initdata = { &amp;nbsp; 
.nr_controllers = 1, &amp;nbsp; 
.preinit = ixdp425_pci_preinit, &amp;nbsp; 
.swizzle = pci_std_swizzle, &amp;nbsp; 
.setup = ixp4xx_setup, &amp;nbsp; 
.scan = ixp4xx_scan_bus, &amp;nbsp; 
.map_irq = ixdp425_map_irq, &amp;nbsp; 
}; &amp;nbsp; 
在此先說明一下這個資料結構的定義，其資料結構原型為struct hw_pci，其定義在arch/arm/mach/pci.h，這是核心版本2.6.31之後，ixdp425_pci則是使用者自行為資料稱呼的名字，__initdata定義為這個資料在核心初始化之後，會給予Free收回使用，至於各個資料成員的說明如下。 &amp;nbsp; 
.nr_controllers目的在指示PCI主端控制晶片的數量，正常來說，只有一個PCI主控端晶片。至於.preinit則是在初始化該PCI主端晶片組的Call Back Function，這也和每一個SoC有所不同，所必須進行的初始化內容也依SoC不盡相同，當註冊一個PCI主端時，第一個被呼叫的副程式，若有需要中斷的設定，必須要在此完成和系統註冊。 &amp;nbsp; 
.setup則是一個Call Back Function Pointer，這個副程式的原型為int ixp4xx_setup(int nr, struct pci_sys_data *sys)，系統在呼叫PCI主控端晶片的時候，將會傳送一個序號nr及一個指標struct pci_sys_data *sys給PCI主控端晶片，這個指標須要填入這PCI主控端晶片可以使用的資源，以下是一個範例： &amp;nbsp; 
struct resource *res; &amp;nbsp; 
res = kzalloc(sizeof(*res) * 2, GFP_KERNEL); &amp;nbsp; 
res[0].name = &quot;PCI I/O Space&quot;; &amp;nbsp; 
res[0].start = 0x00000000; &amp;nbsp; 
res[0].end = 0x0000ffff; &amp;nbsp; 
res[0].flags = IORESOURCE_IO; &amp;nbsp; 
res[1].name = &quot;PCI Memory Space&quot;; &amp;nbsp; 
res[1].start = 0x4b000000; &amp;nbsp; 
res[1].end = 0x4bffffff; &amp;nbsp; 
res[1].flags = IORESOURCE_MEM &amp;nbsp; 
request_resource(&amp;amp;ioport_resource, &amp;amp;res[0]); &amp;nbsp; 
request_resource(&amp;amp;iomem_resource, &amp;amp;res[1]); &amp;nbsp; 
sys-&amp;gt;resource[0] = &amp;amp;res[0]; &amp;nbsp; 
sys-&amp;gt;resource[1] = &amp;amp;res[1]; &amp;nbsp; 
sys-&amp;gt;resource[2] = NULL; &amp;nbsp; 
從以上的註冊系統將會保留所要的資源，而在之前所提的標準的PCI驅動器會協助分配資源給PCI從端，所以之後如何分配及管理這些資源，就不用費心了。.scan是系統要開始掃描在PCI匯流排有插上那些PCI從端時會呼叫的副程式，通常都會直接再輾轉呼叫系統的掃描程式，以下是其範例程式： &amp;nbsp; 
return pci_scan_bus(sys-&amp;gt;busnr, &amp;amp;ixp4xx_ops, sys); &amp;nbsp; 
在以上的sys變數為系統傳過來的，ixp4xx_ops則是使用者所要準備的一些有關PCI匯流排設定的一些HAL Call Back Function，其內容為如下： &amp;nbsp; 
struct pci_ops ixp4xx_ops = { &amp;nbsp; 
.read = ixp4xx_pci_read_config, &amp;nbsp; 
.write = ixp4xx_pci_write_config, &amp;nbsp; 
}; &amp;nbsp; 
上面的read/write為在讀寫前面所談的結構表的方式，這和每一個晶片不同，其控制的位置也不同，所以根據每一顆系統單晶片來寫，而這兩個的函數原型如下： &amp;nbsp; 
int ixp4xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) &amp;nbsp; 
int ixp4xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) &amp;nbsp; 
在系統呼叫進來的匯流排資料結構中成員bus-&amp;gt;number是這個系統中第幾個匯流排，在控制晶片時可能會用到，devfn則是slot number和function number的結合，可以使用巨集指令PCI_SLOT()或PCI_FUNC()分別取得其資訊，size則是表示1、2或4位元組的存取，where則是須要特別注意，它是在存取1、2位元組會用到，在二百五十六位元組結構表的相對位置，大部分的PCI主控端晶片會有boundary存取的問題，這邊須要特別注意做轉換，value則是較簡單，是讀取或寫入所放的值。 &amp;nbsp; 
.map_irq則是當PCI Host在掃描時在要指定IRQ時會呼叫這個副程式，而這個副程式則會回傳要指定的中斷號碼。 &amp;nbsp; 
當以上的資料準備好之後，你須要撰寫一個初始化的進入點，讓系統開機會呼叫這個初始化副程式，以下為其範例： &amp;nbsp; 
int __init ixdp425_pci_init(void) &amp;nbsp; 
{ &amp;nbsp; 
return pci_common_init(&amp;amp;ixdp425_pci); &amp;nbsp; 
} &amp;nbsp; 
subsys_initcall(ixdp425_pci_init); &amp;nbsp; 
由以上的程式碼可以看到，該程式會直接呼叫系統的pci_common_init()而且給它前面所提的資料結構，當呼叫該系統程式時，系統會馬上呼叫所給的資料結構中的Preinit Call Back Function，之後會呼叫Setup Call Back Function，再接著就是呼叫Scan Call Back Function，如此而完成一個PCI主端的載入動作(圖3)。 &amp;nbsp; 







圖3 PCI載入動作流程圖
最後記得使用巨集指令subsys_initcall()，將所完成的副程式註冊為一個開機會被呼叫的副程式。 &amp;nbsp; 
透過暫存器產生I/O訊號　化解ARM僅具備記憶體存取限制&amp;nbsp; 
原則上，上述應該就完成PCI主端的移植，因為在移植時只要完成這部分會和硬體有關的硬體抽象層即可，但是還是有一些地方必須注意，首先，在x86的平台上是有所謂的I/O存取，CPU本身就有此支援，CPU對周邊元件的存取方式，本來就有兩種，一種是記憶體存取，一種是I/O存取，而在PCI匯流排也有這兩種的存取方式，所以這兩種不同的存取方法，被視為兩種不同的資源，但是在ARM中央處理器中，沒有I/O存取，僅有記憶體存取，因此撰寫驅動程式會針對I/O存取使用inb()、oub()、inw()、outw()、inl()、outl()等副程式，若是記憶體存取則會使用readb()、writeb()、readw()、writew()、readl()、writel()等副程式，因為ARM中央處理器並沒有I/O存取的功能，所以在HAL層會改寫inx()、outx()等副程式內容，改成使用記憶體存取(圖4)。 &amp;nbsp; 







圖4 CPU存取示意圖
另外，I/O存取驅動程式所使用的資源，並不會將其轉換為虛擬位址，可能產生非法存取記憶體位置，因為核心須要使用虛擬位址驅動所有的程式碼，這一個部分可透過修改PCI從端的驅動程式碼化解疑慮，但缺點是原始碼只能使用在ARM平台，其他如x86的平台將無法採用相同的方法，另外也必須面臨修改驅動程式，因此並不是受歡迎的選擇。另一個解決方法是修改PCI主端的資源分配，就是之前有提到在初始化時須要將可分配的資源向系統註冊，註冊前先將其轉換為虛擬位址，再向系統註冊，此方法的優點為修改幅度小，且可避免如前一個方法的疑慮。 &amp;nbsp; 
值得注意的是，PCI主端的晶片有兩種，一種是其本身對PCI匯流排兩種不同存取方式的自動轉換，如果PCI從端是使用I/O存取方式的周邊，它會自動將ARM中央處理器的記憶體存取方式，自動轉換為I/O存取方式，所以將可達成前面對於第二種I/O存取的修改方式，而對於ARM中央處理器的記憶體存取方式，則直接轉換至PCI匯流排即可，對於PCI主控端晶片可省略很多工夫。但是有另外一種PCI匯流排晶片卻無法依此方法，這種晶片比較麻煩，必須將其中的一些暫存器在PCI匯流排上產生I/O存取的訊號，以下則是其寫法說明。 &amp;nbsp; 
首先，必須在arch/arm/mach-xxxx的目錄之下，建立一個檔案include/mach/io.h，注意其路徑及檔名不可更改，因為在整個核心原始碼中的Makefile及編譯時要尋找C語言的include file路徑都已寫好，更改將會造成編譯錯誤，在這個檔案之中將可以改寫ARM中央處理器已內定改好的inx()及outx()的副程式，若在這個檔案之中宣告如下： &amp;nbsp; 
#define __io(v) __typesafe_io(v) &amp;nbsp; 
表示使用ARM中央處理器中己改好的inx()及outx()副程式，這是使用PCI主端會自動轉換I/O存取至PCI匯流排的晶片，若不是所需要的修改如下： #define outb(p, v) __ixp4xx_outb(p, v) &amp;nbsp; 
#define outw(p, v) __ixp4xx_outw(p, v) &amp;nbsp; 
#define outl(p, v) __ixp4xx_outl(p, v) &amp;nbsp; 
#define outsb(p, v, l) __ixp4xx_outsb(p, v, l) &amp;nbsp; 
#define outsw(p, v, l) __ixp4xx_outsw(p, v, l) &amp;nbsp; 
#define outsl(p, v, l) __ixp4xx_outsl(p, v, l) &amp;nbsp; 
#define inb(p) __ixp4xx_inb(p) &amp;nbsp; 
#define inw(p) __ixp4xx_inw(p) &amp;nbsp; 
#define inl(p) __ixp4xx_inl(p) &amp;nbsp; 
#define insb(p, v, l) __ixp4xx_insb(p, v, l) &amp;nbsp; 
#define insw(p, v, l) __ixp4xx_insw(p, v, l) &amp;nbsp; 
#define insl(p, v, l) __ixp4xx_insl(p, v, l) &amp;nbsp; 
設計者必須針對每一個副程式重新定義至另一個改寫的內容，而這些改寫的內容，則是針對所使用的PCI主端晶片進行控制，請參考以下的範例： &amp;nbsp; 
static inline void &amp;nbsp; 
__ixp4xx_outb(u8 value, u32 addr) &amp;nbsp; 
{ &amp;nbsp; 
u32 n, byte_enables, data; &amp;nbsp; 
n = addr % 4; &amp;nbsp; 
byte_enables = (0xf &amp;amp; ~BIT(n)) &amp;lt;&amp;lt; IXP4XX_ PCI_NP_CBE_BESL; &amp;nbsp; 
data = value &amp;lt;&amp;lt; (8*n); &amp;nbsp; 
.............................. &amp;nbsp; 
} &amp;nbsp; 
............................ &amp;nbsp; 
static inline u8 &amp;nbsp; 
__ixp4xx_inb(u32 addr) &amp;nbsp; 
{ &amp;nbsp; 
u32 n, byte_enables, data; &amp;nbsp; 
n = addr % 4; &amp;nbsp; 
byte_enables = (0xf &amp;amp; ~BIT(n)) &amp;lt;&amp;lt; IXP4XX_ PCI_NP_CBE_BESL; &amp;nbsp; 
.......................... &amp;nbsp; 
return data &amp;gt;&amp;gt; (8*n); &amp;nbsp; 
} &amp;nbsp; 
................................. &amp;nbsp; 
另外幾個和I/O有關的副程式也必須重新改寫如下： &amp;nbsp; 
#define ioread8(p) __ixp4xx_ioread8(p) &amp;nbsp; 
#define ioread16(p) __ixp4xx_ioread16(p) &amp;nbsp; 
#define ioread32(p) __ixp4xx_ioread32(p) &amp;nbsp; 
#define ioread8_rep(p, v, c) &amp;nbsp; 
__ixp4xx_ioread8_rep(p, v, c) &amp;nbsp; 
#define ioread16_rep(p, v, c) &amp;nbsp; 
__ixp4xx_ioread16_rep(p, v, c) &amp;nbsp; 
#define ioread32_rep(p, v, c) &amp;nbsp; 
__ixp4xx_ioread32_rep(p, v, c) &amp;nbsp; 
#define iowrite8(v,p) &amp;nbsp; 
__ixp4xx_iowrite8(v,p) &amp;nbsp; 
#define iowrite16(v,p) &amp;nbsp; 
__ixp4xx_iowrite16(v,p) &amp;nbsp; 
#define iowrite32(v,p) &amp;nbsp; 
__ixp4xx_iowrite32(v,p) &amp;nbsp; 
#define iowrite8_rep(p, v, c) &amp;nbsp; 
__ixp4xx_iowrite8_rep(p, v, c) &amp;nbsp; 
#define iowrite16_rep(p, v, c) &amp;nbsp; 
__ixp4xx_iowrite16_rep(p, v, c) &amp;nbsp; 
#define iowrite32_rep(p, v, c) &amp;nbsp; 
__ixp4xx_iowrite32_rep(p, v, c) &amp;nbsp; 
#define ioport_map(port, nr) &amp;nbsp; 
((void __iomem*)(port + PIO_OFFSET)) &amp;nbsp; 
#define ioport_unmap(addr) &amp;nbsp; 
#define PIO_OFFSET 0x10000UL &amp;nbsp; 
#define PIO_MASK 0x0ffffUL &amp;nbsp; 
#define __is_io_address(p) &amp;nbsp; 
(((unsigned long)p &amp;gt;= PIO_OFFSET) &amp;amp;&amp;amp; &amp;nbsp; 
((unsigned long)p&amp;lt;=(PIO_MASK + PIO_OFFSET))) &amp;nbsp; 
static inline unsigned int &amp;nbsp; 
__ixp4xx_ioread8(const void __iomem *addr) &amp;nbsp; 
{ unsigned long port = (unsigned long __force)addr; &amp;nbsp; 
if (__is_io_address(port)) &amp;nbsp; 
return (unsigned int)__ixp4xx_inb(port &amp;amp; PIO_MASK); &amp;nbsp; 
else return (unsigned int)__ixp4xx_readb(addr); &amp;nbsp; 
} &amp;nbsp; 
.......................................... &amp;nbsp; 
static inline void &amp;nbsp; 
__ixp4xx_iowrite8(u8 value, void __iomem *addr) &amp;nbsp; 
{ &amp;nbsp; 
unsigned long port = (unsigned long __force)addr; &amp;nbsp; 
if (__is_io_address(port)) &amp;nbsp; 
__ixp4xx_outb(value, port &amp;amp; PIO_MASK); &amp;nbsp; 
Else &amp;nbsp; 
__ixp4xx_writeb(value, addr); &amp;nbsp; 
} .................................... 
除此之外，有些PCI主端的晶片對於ARM中央處理器的記憶體存取方式，也不會直接自動轉換至PCI匯流排，和I/O存取一樣必須控制PCI主端晶片，進而產生一個PCI匯流排上的記憶體存取，其改寫內容十分類似I/O改寫，若不須要改寫，使用ARM中央處理器內定的程式碼則必須有以下的宣告： &amp;nbsp; 
#define __mem_pci(a) (a) &amp;nbsp; 
若要改寫以下為其範例： &amp;nbsp; 
#define writeb(v, p) __ixp4xx_writeb(v, p) &amp;nbsp; 
#define writew(v, p) __ixp4xx_writew(v, p) &amp;nbsp; 
#define writel(v, p) __ixp4xx_writel(v, p) &amp;nbsp; 
#define writesb(p, v, l) __ixp4xx_writesb(p, v, l) &amp;nbsp; 
#define writesw(p, v, l) __ixp4xx_writesw(p, v, l) &amp;nbsp; 
#define writesl(p, v, l) __ixp4xx_writesl(p, v, l) &amp;nbsp; 
#define readb(p) __ixp4xx_readb(p) &amp;nbsp; 
#define readw(p) __ixp4xx_readw(p) &amp;nbsp; 
#define readl(p) __ixp4xx_readl(p) &amp;nbsp; 
#define readsb(p, v, l) __ixp4xx_readsb(p, v, l) &amp;nbsp; 
#define readsw(p, v, l) __ixp4xx_readsw(p, v, l) &amp;nbsp; 
#define readsl(p, v, l) __ixp4xx_readsl(p, v, l) &amp;nbsp; 
static inline void &amp;nbsp; 
__ixp4xx_writeb(u8 value, volatile void __iomem *p) &amp;nbsp; 
{ &amp;nbsp; 
.................................... &amp;nbsp; 
if (addr &amp;gt;= VMALLOC_START) { &amp;nbsp; 
__raw_writeb(value, addr); &amp;nbsp; 
return; &amp;nbsp; 
} &amp;nbsp; 
............................. &amp;nbsp; 
} &amp;nbsp; 
.................................... &amp;nbsp; 
/* &amp;nbsp; 
* We can use the built-in functions b/c they end up calling writeb/readb &amp;nbsp; 
*/ &amp;nbsp; 
#define memset_io(c,v,l) _memset_io((c),(v),(l)) &amp;nbsp; 
#define memcpy_fromio(a,c,l) &amp;nbsp; 
_memcpy_fromio((a),(c),(l)) &amp;nbsp; 
#define memcpy_toio(c,a,l) &amp;nbsp; 
_memcpy_toio((c),(a),(l)) &amp;nbsp; 
PCI轉記憶體為虛擬位址&amp;nbsp; 
最後仍一個問題須要特別注意，通常使用記憶體存取之前，可以將一個實體記憶體轉換為虛擬位址，若PCI主端是前面的方式，須要使用PCI主端來產生一個存取動作，那麼也可改寫ioremap() &amp;amp; iounmap()的副程式，其範例程式如下： &amp;nbsp; 
static inline void __iomem * &amp;nbsp; 
__ixp4xx_ioremap(unsigned long addr, size_t size, unsigned int mtype) { &amp;nbsp; 
if((addr &amp;lt; PCIBIOS_MIN_MEM) || (addr &amp;gt; 0x4fffffff)) &amp;nbsp; 
return __arm_ioremap(addr, size, mtype); &amp;nbsp; 
return (void __iomem *)addr; &amp;nbsp; 
} &amp;nbsp; 
static inline void &amp;nbsp; 
__ixp4xx_iounmap(void __iomem *addr) &amp;nbsp; 
{ &amp;nbsp; 
if ((__force u32)addr &amp;gt;= VMALLOC_START) &amp;nbsp; 
__iounmap(addr); &amp;nbsp; 
} &amp;nbsp; 
#define __arch_ioremap(a, s, f) __ixp4xx_ioremap(a, s, f) &amp;nbsp; 
#define __arch_iounmap(a) __ixp4xx_iounmap(a) &amp;nbsp; 
到達此步驟，應該已經可以完成PCI主端程式的設定，而且可以讓PCI從端的程式具有相容性，且可使用於多種中央處理器之下，建立這種相容性的目的，主要是因為PCI從端的驅動程式可能由晶片廠商提供，但是只有在x86的平台測試過，為了可以正確地使用這些原始碼，了解以上述所提及的概念為當務之急。 &amp;nbsp; 
(本文作者為艾鍗學院教學中心講師) </description>
		<pubDate>Sun, 20 Feb 2011 16:37:10 +0800</pubDate>
	</item>
	<item>
		<title>RS232 Adapter Sch.</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=4440</link>
		<description>&amp;nbsp;
RS-232 Level Converters/Shifter
&amp;nbsp;
Null Modem Wiring Diagram
&amp;nbsp;PC (+/- 12V)&amp;lt;-----------&amp;gt;MAX232&amp;lt;----------------&amp;gt; MCU or sendor&amp;nbsp; 3.3V~5V
&amp;nbsp;&amp;nbsp; RS232&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TTL
&amp;nbsp;
&amp;nbsp;


&amp;nbsp;
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
--------------------&amp;nbsp;
&amp;nbsp;RS232&amp;lt;-----------&amp;gt;MAX232&amp;lt;----------------&amp;gt;TTL
&amp;nbsp;TTL&amp;lt;----------------&amp;gt;TTL
&amp;nbsp;
RS232 Standard
&amp;nbsp; </description>
		<pubDate>Mon, 14 Feb 2011 00:16:21 +0800</pubDate>
	</item>
	<item>
		<title>如何使用示波器的觸發功能來進行除錯</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=3729</link>
		<description>什麼是觸發？ 

沒有一台示波器會擁有無限大的記憶體，因此所有的示波器都必須使用觸發（trigger）。觸發是指使用者所關心，而示波器必須發現的一個事件。換言之，它是使用者在波形中想要找到的某種情況。觸發可能是代表波形中的問題的一個事件，但不必然如此。觸發的例子包括信號緣、突波與數位碼型。有限的記憶體迫使示波器必須使用觸發
&amp;nbsp;
示波器的記憶體可以想成是一條輸送帶。每當擷取到新的取樣，便會將它放入記憶體中。當記憶體滿了之後，最早擷取到的取樣就會被捨棄，因此記憶體只會包含最新的取樣。當觸發事件發生時，示波器會擷取足夠的額外取樣，以便將觸發放在要求的記憶體位置（通常在中間），然後將資料顯示給使用者。
&amp;nbsp;
....http://www.eettaiwan.com/ART_8800549438_480402_TA_9dc21054.HTM </description>
		<pubDate>Thu, 09 Dec 2010 23:25:08 +0800</pubDate>
	</item>
	<item>
		<title>USART and UART</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=3694</link>
		<description>&amp;nbsp;8250/ 16550 Regiest table
&amp;nbsp;
&amp;nbsp;http://www.beyondlogic.org/serial/serial.htm#13
&amp;nbsp;
Part 2 : Serial Ports&#039; Registers (PC&#039;s)
Interrupt Enable Register (IER)Interrupt Identification Register (IIR)First In / First Out Control Register (FCR)Line Control Register (LCR)Modem Control Register (MCR)Line Status Register (LSR)Modem Status Register (MSR)Scratch Register
&amp;nbsp;
---------------
CSRC: Clock Source Select bitAsynchronous mode: Don’t care.&amp;nbsp; 
Synchronous mode: 1 = Master mode (clock generated internally from BRG)0 = Slave mode (clock from external source) 
&amp;nbsp;
---------------------------
UART - Universal Asyncronous Receiver Transmitter USART - Universal Syncronous Asyncronous Receiver Transmitter 
&amp;nbsp;
In synchronous mode the device require both data and clock. The clock is recovered from the data or an external one which is in synchrounous with data.In asynchronous mode the device requires only data. The data clock is internally generated and synchronised with start and stop bits embedded in the data received
&amp;nbsp;
In uart data is send byte by byte. one start bit and 1 or 2 stop bits are attached with a byte. The max speed for the data can be upto 100kps. In USART data is send in the form of blocks. 
&amp;nbsp;
&amp;nbsp;
The word &quot;asynchronous&quot; indicates that UARTs recover character timing information from the data stream, using designated &quot;start&quot; and &quot;stop&quot; bits to indicate the framing of each character.
&amp;nbsp;
&amp;nbsp;In synchronous transmission, the clock data is recovered separately from the data stream and no start/stop bits are used. This improves the efficiency of transmission on suitable channels; more of the bits sent are data. 
&amp;nbsp;
&amp;nbsp;
An asynchronous transmission sends nothing over the interconnection when the transmitting device has nothing to send; but a synchronous interface must send &quot;pad&quot; characters to maintain synchronism between the receiver and transmitter. The usual filler is the ASCII &quot;SYN&quot; character. This may be done automatically by the transmitting device.Some chips have both synchronous and asynchronous modes. These are called USARTs (for &quot;universal synchronous asynchronous receiver-transmitters&quot;) </description>
		<pubDate>Tue, 07 Dec 2010 16:09:08 +0800</pubDate>
	</item>
	<item>
		<title>GPL license</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=3309</link>
		<description>使用linux 開發, 要注意到open source GPL license
的問題,不僅要提供source ,還要將產品中包含到open sourc的部份表列出來
如附件檔... </description>
		<pubDate>Fri, 05 Nov 2010 22:20:49 +0800</pubDate>
	</item>
	<item>
		<title>[作業]raw socket 程式練習</title>
		<link>http://lms.xms.com.tw/board.php?courseID=143&amp;f=doc&amp;cid=3186</link>
		<description>&amp;nbsp;
&amp;nbsp;附件為 ping 程式範例檔,請試著修改
&amp;nbsp;使其完成ping 功能
&amp;nbsp;
&amp;nbsp;keyword : raw socket, ICMP
&amp;nbsp;
&amp;nbsp; </description>
		<pubDate>Thu, 21 Oct 2010 14:53:19 +0800</pubDate>
	</item>
	</channel>
	</rss>
