2014年12月24日 星期三

STM32 DMA軟體式FIFO程式

用在通信及ADC上,使用DMA循環式架構。利用DMA上的計數器做為FIFO控制。
其中USART1_BUFFER_SIZE,要設定在DMA的大小中。
 USART1_Buffer[]也是DMA所使用的。

unsigned short last_count;

void Reset_USART1_Buffer(void)
{
    last_count = DMA_GetCurrDataCounter(DMA2_Stream5);
}

int Get_USART1_Value(unsigned char *Value)
{
    unsigned short current_count;
    int  pos;

    current_count = DMA_GetCurrDataCounter(DMA2_Stream5);
    if ( current_count != last_count )
    {
        pos = USART1_BUFFER_SIZE - last_count;
        *Value = USART1_Buffer[pos];
        last_count--;
        if (last_count <= 0)
        {
            last_count = USART1_BUFFER_SIZE;
        }
        return -1;
    }
    else
    {
        return 0;
    }
}


因為已用DMA,軟體過一段時間去收就好了,完全無需使用中斷。

2014年12月22日 星期一

Encoder使用

這個月被二位網友問到Encoder問題。
Bee看過很多MCU工程師寫的程式,大部分工程師將I/O暫存器當RAM用。
但實際上硬體不穩定時,就查得要死要活的,很難穩定系統,又不知問題在那裏。
Bee也是過來人,因為早期Bee也寫過不穩定的硬體(用FPGA),軟體上吃了大虧,自此養成必要時才動硬體暂存器的習慣。
也就是使用Encoder,必要時才讀,再轉成32位元變數(64位元也可以),以32位元為其他軟體的依據。
這招不僅是減少對硬體的依賴度,也增加不同平台的可移植性。
同樣的Encoder程式,用在數個案子內:
1. 8051,使用中斷方式解Encoder,可用。
2. FPGA,使用I/O讀取24位元,可用。
3. STM32,內建Encoder,16位元,可用。
上層馬達控制程式完全不用修改。

其中有幾行連博士也覺得神奇,找過各大網站,就是找不到為何可以用。
以STM32系統為例:

int Encoder_Count;
unsigned short Last_Encoder;

void GetEncoder(void)
{
    unsigned short Encoder = 0;
    int Encoder_Diff;
   
    Encoder = TIM_GetCounter(ENC_TIMER);
    Encoder_Diff = (short)(Encoder - Last_Encoder);
    Last_Encoder = Encoder;
    Encoder_Count += Encoder_Diff;
}

Encoder_Count就是32位元Encoder的值,一樣不管Encoder暫存器是16/24位元,都先轉成32位元。
之後再重新計算,看是單向運動,圓週運動,基本上32位元都不會掉精度。

Encoder_Diff = (short)(Encoder - Last_Encoder);
此行則是利用unsigned在計算時underflow/overflow的特性得到差值,這是一般人不會使用的。

2014年12月6日 星期六

在FATFS Sample中新增PC檔案交換功能

FATFS可以在PC上模擬,是利用記憶體做的一個Disk,但創造後是空的,難以做其他實驗。所以新增二個指令可以將檔案搬進Fatfs系統及搬出Fatfs系統。

搬入指令fy,程式碼如下:

            case 'y' :    /* fy <src_name> <dst_name> - Copy a file from PC*/
                while (*ptr == ' ') ptr++;
                ptr2 = _tcschr(ptr, ' ');
                if (!ptr2) break;
                *ptr2++ = 0;
                while (*ptr2 == ' ') ptr2++;
                _tprintf(_T("Opening PC file \"%s\""), ptr);
                fp = fopen(ptr,"rb");
                _tprintf(_T("\n"));
                if (!fp) {
                    _tprintf(_T("Open Fail!\n"));
                    break;
                }
                while (*ptr2 == ' ') ptr2++;
                _tprintf(_T("Creating \"%s\""), ptr2);
                res = f_open(&file[1], ptr2, FA_CREATE_ALWAYS | FA_WRITE);
                _tprintf(_T("\n"));
                if (res) {
                    put_rc(res);
                    f_close(&file[0]);
                    break;
                }
                _tprintf(_T("Copying..."));
                p1 = 0;
                for (;;) {
                    s1 = fread(Buff, 1, sizeof Buff, fp);
                    if (s1 == 0) break;   /* error or eof */
                    res = f_write(&file[1], Buff, s1, &s2);
                    p1 += s2;
                    if (res || s2 < s1) break;   /* error or disk full */
                }
                _tprintf(_T("\n"));
                if (res) put_rc(res);
                fclose(fp);
                f_close(&file[1]);
                _tprintf(_T("%lu bytes copied.\n"), p1);
                break;


搬出指令fz,程式碼如下:
            case 'z' : /* fz <src_name> <dst_name> - Copy a file to PC*/
                while (*ptr == ' ') ptr++;
                ptr2 = _tcschr(ptr, ' ');
                if (!ptr2) break;
                *ptr2++ = 0;
                while (*ptr2 == ' ') ptr2++;
                _tprintf(_T("Opening \"%s\""), ptr);
                res = f_open(&file[0], ptr, FA_OPEN_EXISTING | FA_READ);
                _tprintf(_T("\n"));
                if (res) {
                    put_rc(res);
                    break;
                }
                while (*ptr2 == ' ') ptr2++;
                _tprintf(_T("Creating PC file \"%s\""), ptr2);
                fp = fopen(ptr2,"wb");
                _tprintf(_T("\n"));
                if (!fp) {
                    _tprintf(_T("Open Fail!\n"));
                    break;
                }
                _tprintf(_T("Copying..."));
                p1 = 0;
                for (;;) {
                    res = f_read(&file[0], Buff, sizeof Buff, &s1);
                    if (res || s1 == 0) break;   /* error or eof */
                    s2 = fwrite(Buff, 1, s1,fp);
                    p1 += s2;
                    if (s2 < s1) break;   /* error or disk full */
                }
                _tprintf(_T("\n"));
                if (res) put_rc(res);
                f_close(&file[0]);
                fclose(fp);
                _tprintf(_T("%lu bytes copied.\n"), p1);
                break;

程式基礎是從fx指令改出來的。

2014年11月27日 星期四

Cortex-M7核心新增特色

找了一些資料,才弄清楚多了那些。主要是針對Cortex-M4之間的差異。

1. 核心改為六級管線加上分支預測
2. Bus界面改為64位元,除增加效率外,增加定址能力對於大型儲存週邊有很大的幫助。
3. 核心正式放入近端記憶體。
   可增加對Call Stack存取速度,改進RTOS效能。
   也有可執行區,可以將需要高速執行程式碼放入,改善中斷效能。
4. 新增硬體除法指令

2014年11月19日 星期三

MCU推展最大障礙在於對軟體操作能力

調部門已四個月,原先進技術部門已分解,重新分配到電子部門。
在新案開發上,軟體人員具有否決權。
使用新式電路,因為以前研究過軟體驅動方式,將電路放內產品。
結果軟體部門否決,因為無法控制,要求舊式電路。
不只如此,對特定廠牌MCU也有依賴性。所以也不易更換MCU。

目前看到二個原因造成MCU升級或更換後的障礙,造成軟體人員不願更換。
1.  對於MCU信號操作的陌生。
    不想量信號的軟體人員會如此,和畢業科系無關。一但投入軟體,便不再碰信號。
2.  對於軟體主架構過度依賴。
    對於慣用8/16位元MCU的軟體人員,已經開發大量函式庫,不願去改舊程式碼。
    常見於接手的工程師,對於原軟體系統並不是很了解,不想動原系統。
    在非RTOS系統上開發的舊程式,此現象特別嚴重。
    因為RTOS就是將軟體和硬體作適當分離。一但沒有O.S.連最基礎的延時功能都大受MCU架構所影響。
    無RTOS的系統本身其移植性就很低。

對於一年要換數個MCU的Bee來說,是早已克服的問題。
這也許是MCU系統工程和MCU軟體工程上的差異。
不過MCU軟體工程,不是PC上的軟體工程,可以完全不碰信號的。       

2014年10月25日 星期六

Forth語言在Swarm發展之可行性

1.  Forth語言之困境
    身為Forther是不會願意接受這件事,但此為現狀,Bee很早就認為,只是隨ARM MCU之流行,情況更加嚴重。
    Forth因為小而完整發揮MCU能力,確實在8/16位元MCU上一直有特色。
    但隨著時代推展,進入32位元MCU時代,小而完整之特質已無法凸顯其特色。
    32位元MCU時代的特性為:
    1.  豐富週邊
    2.  大量免費C函式庫
    3.  大量免費軟體工具
        RTOS, FAT File System, USB Driver, Ethernet Example, GUI Library, SD Card Driver...等等。
    以上特色,使得MCU以C發展可以快速得到成果,Forth則無廠商願意寫函式庫,變得跟不上時代。
    32位元MCU各大廠又以軟體元件為其發展重點,快速拼裝已成為特性,大大的拉開C語言及其他語言的距離。
    32位元MCU除了C外,其他語言完全變成非主流。
   
2.  Swarm Robot / Multi-Robot System發展之問題
    Robot一直是MCU實現的好目標。使用Forth發展是很方便的。但因MCU隨著32位元時代來臨,Forth被淡忘。
    實際上單一Robot發展並不是很方便,若非C語言在MCU上有大量的工具,使用C語言是一項沒有得選擇的發展。
    Bee曾認為Forth在Robot上的發展可能有一席之地。但32位元MCU推展過於快速,完全沒有給Forth有時間及機會去成長。
    在一個偶然的機會,Bee想到找群體機器人(Swarm)上的相關資料,發現以目前的Robot發展是困難的。
    主因為在於Swarm Robot除了實現Robot外,需要解決Robot之間溝通之問題。
    實現通信不難,但Robot之間溝通,實為發展社會語言,若非有電腦語言發展能力,此問題不易解決。
    一般實作Robot,多以電子為主,語言只是實現工具,故一般工程師無法有效解決此問題。
    常用工具C語言在此問題上,完全是缺乏應用之空間。故在此領域推展很慢。
   
3.  Forth如何解決Robot通信及Swarm程式發展之可能
    Forth寫Robot程式和C寫Robot有很大的不同。
    C語言寫Robot比較像是外科手術:
    1. Robot關閉;  麻醉
    2. 寫程式下載; 開刀
    3. Robot打開;  叫醒
    但此程序對於多機器人的程式發展及測試是不利的。
    因為有很多狀況是機器人已經面對和另一個機器人要做溝通協調,外科手術反而打斷取得狀況的方法。
    Forth寫Robot程式則是像老師教學生:
    學生接受老師的指令,一步步動作。有新狀況也可以回報,並加以修正。
    在Swarm的環境,所有的通信都變成廣播型式的指令。
    Forth原先只有一個對象,在此環境中,只要增加指定對象的指令、交換資料的指令,就可以開始使用。
    此時程式設計師成為教練,每一個機器都是學生、學生間可以交換資料,並下命令改變其他學生的工作。
    故Forth可以直接成為Swarm Robot的自然語言,人機一體語言在此環境是極為自然的溝通。
    在通信格式上,幾乎只要將Forth指令用通信封包包一下就可以直接使用。
   
結論:
    Bee認為Forth的衰退是時代的必然。但Forth要能使用下去必須找一個符合的環境。
    只是經過長久的觀察才找出可以有效利用Forth特性的使用場所。
    另一個說法是:C語言在MCU上已是霸主。
    Forth在單打獨鬥上是輸C不少,所以就不要單打,改打群體戰。
    在群體戰這個新領域Forth再利用其小而完美的特性重新站起來。

2014年10月18日 星期六

Cortex M7面世對其他MCU影響

日前ARM發表了Cortex-M7 MCU核心。就規格上來看並沒有多出Cortex-M4很多。
其實因為Cortex-M7和Cortex-A5已有部分市場重疊,所以並沒有一口氣做出很大的超越。
不過倒是另一家公司的產品可慘了: PIC32。
PIC32是一直向Bee推廣,但Bee認為MPIS核心已不會成為主流,所以一直在觀望。
觀望的原因在於PIC32在效能上確實較CM3/4來得強。
但CM4已內建浮點運算器,而PIC32仍遲遲未推出帶有浮點運算器的狀況下,已開始處於劣勢。
唯一只剩下主頻仍強於CM4。
如今最後一項優勢也消失了,CM7可以達到PIC32的同頻且具備浮點運算器。
這下PIC32已完全失去硬體優勢。
剩下的就是軟體環境了。
就軟體開發性來說STM32系列是相當不錯,完全Open Source。只差會不會拼裝。
Microchip也是不錯,大部分功能也都有,但在核心的部分和MPLab相連。
造成移植上不好弄,有支援到可以直接用,沒支援到要拼裝就麻煩了。

另外一個32位元的MCU是TI的DSP。這顆在浮點運算上沒有問題。
但在實際使用上,週邊輸了一截。
也許在運算上,TI的DSP是有贏。不過STM32則是利用其DMA直通週邊,將週邊管理時間省下來。
使用靈活度上是以STM32來得靈活。

但Bee也發現大部分工程師即使已知MCU輸人一截的狀況下,大部分仍不願換新廠商MCU。
主因是要閱讀的資料量過大,要能有效運用,真的要花一點時間。在專案的壓力下,通常不採用新MCU。

MCU現在入門,不管是那一顆其資料手冊都破千頁。這個才是推展上的最大問題。
所以一時三刻,不會有明顯改變,但長期來看,應是很明顯了。