2013年7月6日 星期六

MCU應用面的改變

今年MCU大廠合併一堆是前所未有的局面。ARM可以說近乎統一新MCU市場。

CPU核心是沒得好玩了,所以重心應轉到其他領域才是。

問題是應往那一個方向?

Bee提出一點看法,接下來會極端化。

1. 省電:
  保持小型系統,和8位元搶市場。

2. PC化
  要和PC相連接,擴張使用廣度。或是和手機及平板電腦相連接。
  問題是連接後會以何種方式呈現?
  以USB PnP的功能來說,一定要會產生新裝備,但Bee不認為新裝置的PID來得及加入。
  另一個是使用以前熟悉的界面。像是HID或Mass Storage等裝置,如此一來就不用安裝Driver這樣麻煩的事。
  個人覺得檔案系統是一個最容易呈現的界面。

新元素加入,再來就是市場變化。等著看時代改變了。


2013年5月24日 星期五

X86式微,已經回不來了

Bee最近換了手機,終於開始使用智慧手機了。
一看規格:四核心、2GB RAM及16GB儲存空間。
這規格超過七年前Bee的第一台筆電。
而最近Bee也有點想買NB,只是換手機先。
但低價NB,就i3,i5核心,沒有一台可以使用到16GB的記憶體,只能到8GB。
那NB除了硬碟容量大,64位元CPU外已沒有什麼特性了。以手機前進的速度,4GB記憶體很快會出現。
RAM的容量根本不是優勢。
NB規格上前進的速度,遠不及手機。
只有軟體環境差異,但Bee認為這點撐不了太久。
因為6502轉成X86也是一二年內就翻過來。
DOS被Win95取代也是。
NB被手機取代應該也是很快。

以SD卡做為MCU磁碟機

外部串列式儲存單元選用考量:
1.界面速度
2.單位儲存價格
3.和PC做資料交換

使用USB是一個不錯的選擇,但不是每一種MCU有USB界面。
使用UART是最普遍,但串列儲存元件未支援。
使用I2C則是慢了點。
使用SPI是不錯的選擇,但和PC又無法直通。

用了數種儲存單元後終於出現讓Bee滿意的答案=SD卡。
在界面速度上,速度算不錯。可以使用SDIO的高速模式,也可以用SPI界面,和大部分MCU連接。
在容量單位價格上,可說是非常低。
可以直接拿到PC上讀取,讀卡機容易取得。
若是MCU程式空間小到放不下FAT檔案系統,那也可以全碟讀出,再用PC軟體去分析。
不過已有Open Source解決FAT的問題,就是用FatFs,故就算是8051也是可以使用。

MCU有了大型儲存單元,再加上FAT檔案系統,可做的事就好像變多了。
從前沒有空間做大型資料計算處理,也變得可行。有機會在檔案上做儲存及暫存再轉出結果。
MCU可以做的事就如同DOS時代的PC。
其實環境還真的差不多。
DOS時代的記憶體為640KB,磁碟不到1GB。
現在MCU其RAM大約給64KB,SD卡有4GB。但另有程式空間512KB。
只要控制住RAM的使用量,真的就和DOS環境差不多了。


2013年5月23日 星期四

STM32完整C函式庫支援之可能性

IAR未實現函式列表:

作業系統相關
<stdlib>
abort()
exit()
system()

<signal.h>
raise()
signal()

時間
<time.h>
clock()
time()

檔案系統
<stdio.h>
open()
close()
lseek()
read()
write()
rename()
remove()

若是MCU有支援就可以做其他相關函式的動作。
以STM32來說,有RTC安裝時,可以將time()函式補齊。
若是有檔案系統,例如使用FatFs,也可以補齊。
但作業系統相關的是基於命令列模式,MCU可能沒有人機界面的狀況,仍不會支援。

推論:
DOS時代的程式,差不多可以不用修改就可以移植。


2013年5月22日 星期三

如何產生任意大小的磁碟影像

在使用FatFs就是為了MCU和PC之間可以做檔案交換。
也是Bee第一次在MCU上使用到64位元整數變數。
這種變數數值太大想都沒想過。但遇到檔案系統位址索引就非用不可。

FatFs可以在PC上進行模擬,會產生一個Ram Disk。
不過這個Ram Disk沒有和真實世界相通。
是可以載入SD卡影像檔,但抓取費時。

本想用其他Ram Disk的影像檔來用。結果沒想到Windows有內建。
就在控制台->系統管理工具->電腦管理->磁碟管理
可以在硬碟上產生一個新的碟。
設定上要使用固定大小,不然無法對應真實磁碟。
可以格式化,放入檔案。操作完畢後中斷連接。
再來就可以用檔案讀入的方式Copy進Ram中,給FatFs做為Disk影像用。


2013年5月12日 星期日

從CPU公司併購看科技之發展

Bee一向後知後覺:


Intel賣掉ARM核心一年後才知。


MIPSImagination Technologies併購半年才知。


這二件事時代不同,看似無關,卻是電腦科技的重要分叉路。


Intel賣掉ARM核心,Bee當時認為是不合理的事,ARM核是發展PDA的核心,Intel擺明要失去PDA市場。過了幾年,結果更慘,PDA和手機完全合體後,ARM處理器已經成為主流CPU之一。


至於MIPS被併,則可以見得,GPU的重要性已經和CPU不相上下。


 


那就電腦科技來說,路又是如何走的。


CPU一開始因需求計算力,在達到有效需求的運算力之前,其他功能皆不是重點。Intel在計算力的推展符合需求,造就了帝國企業。


CPU發展到64位元時,就出現了應用需求減緩,正代表已達到基本需求運算力。再來就會有其他問題出現,此時PDA興起,代表能量效率的需求,ARM因此發展成霸主。就目前來看,x86指令解碼電路至少是ARM的三倍,長期下去x86絶非對手。


GPU公司併購CPU公司,代表CPU已無新公司生存空間,也代表GPU已開始和CPU平起平坐。


GPU是如何和CPU能平起平坐,一般人應是無法理解。其實在生物上已經發現相同的問題,解法也是一樣,同時使用。


生物解決自然界問題,和科技是相同的。應是說工程問題相同,只是解決材料不同。在生物從單一感測細胞進展到多重感測細胞,最終發展出視覺細胞,就開始遇到計算問題。邏輯運算和影像運算無法使用同一種單元來做,應說是同是腦細胞,但二者所需的連結結構不同,無法同時存在。於是大腦就分成二個腦,一個做為邏輯運算而另一個做為影像運算。發展了上億年,二個大腦還是沒有因為是那一個重要,而有特別去發展。有的是同時變大。


電腦科技已經開始走入邏輯運算和影像運算並行發展的年代,但因影像運算較為後起,所以市場空間尚未佔足,還有可以成長的空間。而CPU核心設計的市場則是過了高原期,接下來的發展會比以前慢得多。不信的人,您可以看看,若是您買了一台新PC(NB)您說得出CPU多了什麼功能嗎?就是因為連CPU公司也說不出來,才會多了一堆型號(就這裏多一點,那裏少一點),完全沒有創新的內容。就算有創新,也不是客戶關心的內容。



2013年4月23日 星期二

FatFs使用修改

FatFs可以動作:讀取檔案、寫出檔案皆有執行。


但寫出檔案的日期有問題,因為沒有RTC故無時間資料。


時間資料可以給一個固定值,但固定值由人來填寫不太有利。


利用C語言中的__TIME____DATE__來做為時間常數。


__TIME__的格式為”hh:mm:ss”


是固定的ASCII碼,所以轉成數值無問題。


__DATE__的格式為”Mmm dd yy”


dd yy也是ASCII也無問題。


Mmm為三個英文字,要轉成1~12變得很麻煩。


三個英文字要分成12個月,只要判定後二字就可以分。


只好寫一個switch case去做12個月字母去分類。


最後將__TIME____DATE__const字串去存。


設定有最佳化的Compiler設定後,可以看到反組譯的結果為:


   \                     get_fattime:


   \   00000000   0x....             LDR.N    R0,??DataTable7_4  ;; 0x42938746


   \   00000002   0x4770             BX       LR               ;; return


結果只有二個指令,只回傳定值。


寫了近90行程式,只會編成二個指令,就是4Byte


測試寫入檔案的時間是對的,會是編譯的時間。


程式碼:


#define DC(t,a,b)   (((a)<<8)+(b))
unsigned char const Date[] = __DATE__;
unsigned char const Time[] = __TIME__;

DWORD get_fattime (void)
{
    BYTE rtcYear , rtcMon , rtcMday, rtcHour, rtcMin, rtcSec;
    DWORD time;

#ifdef USE_FS_RTC
    RTC_TimeTypeDef   RTC_TimeStructure;
    RTC_DateTypeDef   RTC_DateStructure;
    /* Get info from RTC here */
    RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);

    rtcSec    =  RTC_TimeStructure.RTC_Seconds;
    rtcMin    =  RTC_TimeStructure.RTC_Minutes;
    rtcHour   =  RTC_TimeStructure.RTC_Hours;

    RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure);

    rtcYear =  RTC_DateStructure.RTC_Year;
    rtcMon =  RTC_DateStructure.RTC_Month;
    rtcMday =  RTC_DateStructure.RTC_Date;
#else
    rtcSec    =  ((Time[6]-'0')*10+(Time[7]-'0'));
    rtcMin    =  ((Time[3]-'0')*10+(Time[4]-'0'));
    rtcHour   =  ((Time[0]-'0')*10+(Time[1]-'0'));
    rtcYear   =  ((Date[9]-'0')*10+(Date[10]-'0')+20);


    rtcMday   =  (Date[4]==' ')? (Date[5]-'0'): ((Date[4]-'0')*10+(Date[5]-'0'));
    switch ((Date[1]<<8)+Date[2])
    {
    case DC('J','a','n') :
        rtcMon = 1;
        break;
    case DC('F','e','b') :
        rtcMon = 2;
        break;
    case DC('M','a','r') :
        rtcMon = 3;
        break;
    case DC('A','p','r') :
        rtcMon = 4;
        break;
    case DC('M','a','y') :
        rtcMon = 5;
        break;
    case DC('J','u','n') :
        rtcMon = 6;
        break;
    case DC('J','u','l') :
        rtcMon = 7;
        break;
    case DC('A','u','g') :
        rtcMon = 8;
        break;
    case DC('S','e','p') :
        rtcMon = 9;
        break;
    case DC('O','c','t') :
        rtcMon = 10;
        break;
    case DC('N','o','v') :
        rtcMon = 11;
        break;
    case DC('D','e','c') :
        rtcMon = 12;
        break;
    default :
        rtcMon = 1;
        break;
    }
#endif
    /* Pack date and time into a DWORD variable */
    time =      (((DWORD)rtcYear) << 25)
             | ((DWORD)rtcMon << 21)
             | ((DWORD)rtcMday << 16)
             | (WORD)(rtcHour << 11)
             | (WORD)(rtcMin << 5)
             | (WORD)(rtcSec >> 1);
    return time;
}