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;
}







2013年3月19日 星期二

CPU市場鐵律:量變引發質變

之前看了對於ARM及X86之爭的評論。有一句話我非常認同:量變引發質變。
意思是當某種型式CPU在市場上佔有數量優勢時,就會形成絶對性優勢。
這和CPU本身品質無關,只因硬體相容性可以讓軟體好好發展。
而要佔有數量,價格不用說一定要夠低,另一種是開放性,非獨家生產。
PC市場因壟斷較看不出來,但MCU卻是很明顯。
8051是8位元MCU的霸主,因為大家都可以做硬體。
16位元來不及有霸主就直接進入32位元MCU時代。
而32位元MCU的霸主正在形成。
硬體統一完畢,再來會變成軟體開始統一。
結果也會有類似的現象,會有統一的軟體架構出現。
又走"量變引發質變"這條路,軟體架構的品質不是重點,而是使用量。

不管軟硬體,使用者習慣才是主導,而市場往使用者多的方向走。


2013年3月16日 星期六

Cortex M4推展不如預期

雖然各廠商將推展主力移往CM4,但在推展上並不是如此順利。
主因是,要浮點運算做什麼?
往8位元MCU轉來的工程師,對於能在32位元上開發程式已是很開心,要玩的一堆,還沒有意識到浮點運算要如何用,那又何必多花錢。
而從PC轉來的工程師對於CM4的執行效能根本看不上眼,去玩Cortex-A8還比較實在,因為Cortex-A8也不貴。
這樣的局面造成CM4不上不下的樣子。
還有各廠商自行發展的32位元處理器,其實Bee也不太看好。

現在市場已經轉成由軟體來主導,要換MCU談何容易。連軟體工具都要換新,那來那個時間。
至少CM3還可以降為CM0或升級為CM4,光是這樣就可以吃很久,那還有機會看別的MCU。
萬一有什麼大的應用,轉到Cortex-A8也是不差的選擇。

MCU現在只是一個骨架系統,再來需求會轉往拼裝系統的速度。
再來就要看工程師如何快速拼裝系統,拼裝快硬體價格低才是重點。


2013年3月14日 星期四

簡單多工於Cortex-M3上最佳化

原程式:


void main(void)


{


    InitSystem();


    INIT_DEVICE();


    while (1)


    {


        switch (Task_State[FuncID])


        {


        case TASK_RUNNING :


            TaskFunc[FuncID]();


            break;


        case TASK_SKIP :


            if ( Task_Delay_Count[FuncID] )


            {


                Task_Delay_Count[FuncID]--;


                if (! Task_Delay_Count[FuncID]) WakeUp(FuncID);


            }


            break;


        default:


            break;


        }


        if ( ++FuncID >= TASK_NUM ) FuncID = 0;


    }


}


 


新程式:


void main(void)


{


    InitSystem();


    INIT_DEVICE();


    while (1)


    {


        register unsigned int   temp_id;


        register unsigned int   temp_delay;


 


        temp_id = FuncID;


        switch (Task_State[temp_id])


        {


        case TASK_RUNNING :


            TaskFunc[temp_id]();


            break;


        case TASK_SKIP :


            temp_delay = Task_Delay_Count[temp_id];


            if ( temp_delay )


            {


                temp_delay--;


                Task_Delay_Count[temp_id] = temp_delay;


                if (! temp_delay) WakeUp(temp_id);


            }


            break;


        default:


            break;


        }


        if ( ++temp_id >= TASK_NUM ) temp_id = 0;


        FuncID = temp_id;


    }


}


因核心程式執行未檢討有無可以改善空間,因此段程式決定各工作間的掃描率,若是可以改善將增加工作效率。


分析原本的程式,發現有多一些記憶體存取動作。


於是將記憶體動作簡化,中間使用暫存器的方式應可以加速。


先將FuncID這個變數用暫存器變數取出,編出來的程式少了一個指令。


又將Task_Delay_Count[]也用暫存器變數,有少一點組合語言指令。


主要廻圈原需要16個指令,現在只剩下12個指令,少了四個指令。


16個指令需要23Clock執行時間,現在12個指令只要19Clock執行時間。


用示波器實測,Skip 1000次需時5.02ms,原先為6.80ms,確實加速執行時間。


 


不過Cortex M3用暫存器變數直接使用int會比shortchar來得有效率。中間會少了正負號擴張指令,所以速度會更快。


 


2013年3月6日 星期三

Cortex-M4開啟新MCU戰場

CM3因為ST已是獨大,所以各廠商就將重心移往CM4


直到最近TI推展CM4時,才發現價格已經壓到US$3以下。


有浮點運算器的MCU是這樣的價格,等於ADC/DAC不用什麼錢。


其他可以用於浮點運算的應用可以普及。


這樣的轉變,離上次Bee認為32位元MCU變革,只過了剛好一年。


32位元浮點運算,已不是8位元MCU可以做的事。


再下來會大量使用的演算法如:


矩陣運算、傅利葉轉換等等,都會變成非常容易達成。


這樣子MCU程式和PC程式之間差異就更小了。


看來只剩作業系統相容度的問題了。


另一個是使用浮點運算時,可能有效能不足需稍長的時間。


使用作業系統將長時間運算程式做為低優先權的運算,這樣的應用會增多。


RTOSCM4的出現將會推展的更快。