2013年12月23日 星期一
MCU可裁切式IO才是主流
各家CM4F其基本結構差不多,常用週邊也是差不多。
但是ST系列有些特性是比別家的好,自然就用得多。
1. Pin腳高度相容
使得在設計上,可以做Cost Down及Function Up方便得多。
2. 豐富週邊
許多內建週邊,就算不用,pin腳也可用做其他用途。
內建未用週邊,在未來性上,使工程師安心,也會使工程師開始想如何來利用。
3. 平衡性
許多公司都有做到可外接SDRAM等功能。但整體配合性以ST較為平衡。
這可能和週邊豐富性是正相關,在使用及調度上方便許多。
但豐富也可能引入其他副效應,就商業行為而言,先吸引使用者才是第一重點。
2013年11月13日 星期三
HEX轉成BMP檔
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <windows.h>
#define SIZE (0x1000000)
#define WIDTH (672)
#define WIDTH_ALIG ((-(WIDTH))&0x3)
#define HEIGHT (6144)
#define BMP_OFFSET 0x436
#define BMP_SIZE ((WIDTH+WIDTH_ALIG)*HEIGHT+BMP_OFFSET)
unsigned char data[SIZE];
unsigned char image[BMP_SIZE];
FILE *src;
FILE *dest;
unsigned int *p_color;
unsigned char *p_data;
unsigned char *p_src;
BITMAPFILEHEADER *p_FileHeader;
BITMAPINFOHEADER *p_InfoHeader;
// unsigned char d0,d1;
unsigned char B2bin(unsigned char *x)
{
int t;
int i;
unsigned short r;
r = 0;
for ( i=0; i<2; i++ )
{
if ( *x <= '9' )
{
t = (*x-'0');
}
else
{
t = (*x-'A'+0xA);
}
r = (r<<4) + t;
x++;
}
return r;
}
unsigned short W2bin(unsigned char *x)
{
int t;
int i;
unsigned int r;
r = 0;
for ( i=0; i<4; i++ )
{
if ( *x <= '9' )
{
t = (*x-'0');
}
else
{
t = (*x-'A'+0xA);
}
r = (r<<4) + t;
x++;
}
return r;
}
void main(void)
{
int i,j,n;
char temp[80];
int byte_count;
unsigned short address;
int record_type;
int flag;
unsigned int img_address;
p_FileHeader = (BITMAPFILEHEADER*)&image[0];
p_InfoHeader = (BITMAPINFOHEADER*)&image[0xE];
p_color = (unsigned int *)&image[0x36];
p_data = &image[BMP_OFFSET];
p_FileHeader->bfType = 'B' | ('M'<<8);
p_FileHeader->bfSize = WIDTH*HEIGHT+BMP_OFFSET;
p_FileHeader->bfOffBits = BMP_OFFSET;
p_InfoHeader->biSize = 40;
p_InfoHeader->biWidth = WIDTH;
p_InfoHeader->biHeight = HEIGHT;
p_InfoHeader->biPlanes = 1;
p_InfoHeader->biBitCount = 8;
p_InfoHeader->biCompression = 0;
p_InfoHeader->biSizeImage = (WIDTH+WIDTH_ALIG)*HEIGHT;
p_InfoHeader->biXPelsPerMeter = 0;
p_InfoHeader->biYPelsPerMeter = 0;
p_InfoHeader->biClrUsed = 0;
p_InfoHeader->biClrImportant = 0;
for (i=0; i<0x100; i++)
{
p_color[i] = (i<<16) | (i<<8) | i; // set gray pattern
}
src = fopen("memory.hex", "rb");
fread(data,1,SIZE,src);
fclose(src);
p_src = &data[0];
temp[0] = 0;
flag = 1;
while ( flag )
{
sscanf(p_src,"%s",temp);
n = strlen(temp);
if ( n == 0 )
{
break;
}
// printf("%s\n",temp);
if (':' != temp[0]) continue;
byte_count = B2bin(&temp[1]);
address = W2bin(&temp[3]);
record_type= B2bin(&temp[7]);
switch ( record_type )
{
case 0: // data record
for( j=0; j<byte_count; j++ )
{
p_data[img_address+address+j] = B2bin(&temp[9+j*2]);
}
break;
case 1: // end
flag = 0;
break;
case 4: // relocate
img_address = ((W2bin(&temp[9]) & 0xfff)<<16);
break;
default:
break;
}
// reset var.
p_src += (n+2);
temp[0] = 0;
}
dest = fopen("CIS.bmp", "wb");
fwrite(image, 1, BMP_SIZE, dest);
fclose(dest);
}
HEX轉成文字檔
寫了小程式轉成資料,可以用於Excel上看。
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <windows.h>
#define SIZE (0x1000000)
#define MEM_SIZE (0x10000)
unsigned char data[SIZE];
unsigned char image[MEM_SIZE];
FILE *src;
FILE *dest;
unsigned char *p_data;
unsigned char *p_src;
unsigned char B2bin(unsigned char *x)
{
int t;
int i;
unsigned short r;
r = 0;
for ( i=0; i<2; i++ )
{
if ( *x <= '9' )
{
t = (*x-'0');
}
else
{
t = (*x-'A'+0xA);
}
r = (r<<4) + t;
x++;
}
return r;
}
unsigned short W2bin(unsigned char *x)
{
int t;
int i;
unsigned int r;
r = 0;
for ( i=0; i<4; i++ )
{
if ( *x <= '9' )
{
t = (*x-'0');
}
else
{
t = (*x-'A'+0xA);
}
r = (r<<4) + t;
x++;
}
return r;
}
void main(void)
{
int i,j,n;
char temp[80];
int byte_count;
unsigned short address;
int record_type;
int flag;
unsigned int img_address;
int first_address_flag = 0;
unsigned int first_address;
unsigned short *w_data;
p_data = &image[0];
src = fopen("memory.hex", "rb");
fread(data,1,SIZE,src);
fclose(src);
p_src = &data[0];
temp[0] = 0;
flag = 1;
while ( flag )
{
sscanf(p_src,"%s",temp);
n = strlen(temp);
if ( n == 0 )
{
break;
}
// printf("%s\n",temp);
if (':' != temp[0]) continue;
byte_count = B2bin(&temp[1]);
address = W2bin(&temp[3]);
record_type= B2bin(&temp[7]);
switch ( record_type )
{
case 0: // data record
if(! first_address_flag )
{
first_address = img_address + address;
first_address_flag = 1;
}
for( j=0; j<byte_count; j++ )
{
p_data[img_address+address+j-first_address] = B2bin(&temp[9+j*2]);
}
break;
case 1: // end
flag = 0;
break;
case 4: // relocate
img_address = ((W2bin(&temp[9]))<<16);
break;
default:
break;
}
// reset var.
p_src += (n+2);
temp[0] = 0;
}
dest = fopen("audio.csv", "w");
w_data = (unsigned short *) &image[0];
for( i=0; i<MEM_SIZE/2; i++)
{
if(*w_data == 0 ) break;
fprintf(dest,"%d\n",*w_data);
w_data++;
}
// fwrite(image, 1, MEM_SIZE, dest);
fclose(dest);
}
2013年11月6日 星期三
Cortex M系列開始進入Tick-Tock時代
沒想到Cortex-M也開始進入這樣的時代。
在今年(2013)年Cortex-M4進入火熱競爭的狀況下,在推展上很快進入價格戰。
也就是功能性推展(Tick)戰正在進行中。但Cost Down(Tock)也已經展開。
可是面對硬體價格低,功能卻不斷增加,但應用推展卻是緩慢的狀況下。
各廠商開始意識到,客戶是無法一口氣能夠控制複雜功能MCU。
韌體開始元件化,而硬體設定簡單化成為目前推展上的重點。
整合開發工具的方便性將會拉開Cortex-M系列和其他MCU開發上的差距。
也就是使用Cortex-M系列的工程師在圖型化界面拉一拉,就可以設定好MCU的工作模式。
反觀傳統MCU還在工程師一行行寫程式的狀況下,產能會逐漸拉開。
MCU功能多樣化,韌體元件化,程式資源的豐富性,PC資源連接。等等加速拉開Cortex M和傳統MCU之間的距離。
價格成為最後的底線,只要Cortex-M壓到多低,傳統MCU就只能更低。
而學MCU不是一二年可以成的,若是學傳統MCU只能在NT10元以下的MCU市場寫程式,可想而知薪水也高不起來。
Tick-Tock的出現,時代轉變。MCU的下一步?
還在觀察!
2013年10月6日 星期日
2013年10月3日 星期四
32位元MCU軟體的改變
2013年9月21日 星期六
2013年8月29日 星期四
ProtoThreads於VS2010下編譯問題
在VS2010下竟然編不出來。
錯誤訊息是說將巨集的東西做變數是不行的。
奇怪了,不是只有取用行號。
發出錯誤的是debugger。
查了一下,要將Debug Information Format設定從/ZI改為/Zi
這個應是除錯用外部資料,可能是有干涉。
總算動起來了。
不過使用行號嵌入巨集應是可以做的。只是少人用。
另外一個C/C++先進功能,將Label做為變數值這個功能在VS2010也是不支援。
手上已有二支程式需要使用Label做為變數值的程式了。
分別用於Coroutine及動態編譯。
但二者皆有函式域限定問題。不過VS2010連這個功能都沒有也不用試了。
寫程式這麼久,開始出現程式寫得出來,編譯器編不出來的狀況。
真的不能限定使用單一語言,編不出來是Compiler的問題,不是人的問題。
程式創作也不應被語言限定。只要CPU可以執行,就一定可以寫得出來。
2013年8月8日 星期四
Protothreads結合簡單多工之構想
因為Protothreads功能限定在單一函式內。
所以Task在程式結構上會分成二部分。
一個是狀態及時間控制,此部分以Protothreads為主要描述。
另外的是資料處理,基本上這部分還是沒有改變。
工作元仍採用動態加入,主要是要限定反應時間。
一度還想用Protothreads為主結構,但發現有限制。
所以仍以簡單多工為主要結構,這樣在簡單多工上產生出來的動作行為仍可以使用。
這樣的程式結構和FPGA上寫法相似,程式分為狀態控制及資料處理。
這種調整,應可以使程式在有作業系統及無作業系統下看起來更為相似。
2013年7月9日 星期二
簡單多工將移轉到Protothreads
並不是不可以讀,而是和PC上寫程式的風格有差異。
Bee很早就知道有Coroutine可以用,但已知的Coroutine只有在FreeRTOS上。
今天找到了Protothreads正是符合需求。
比對簡單多工,只是短時間性延時的實現使用Protothreads做出來,就可以完全取代。
再來就是情境上的使用差異,在實際使用後才能寫出來。
2013年7月6日 星期六
MCU應用面的改變
CPU核心是沒得好玩了,所以重心應轉到其他領域才是。
問題是應往那一個方向?
Bee提出一點看法,接下來會極端化。
1. 省電:
保持小型系統,和8位元搶市場。
2. PC化
要和PC相連接,擴張使用廣度。或是和手機及平板電腦相連接。
問題是連接後會以何種方式呈現?
以USB PnP的功能來說,一定要會產生新裝備,但Bee不認為新裝置的PID來得及加入。
另一個是使用以前熟悉的界面。像是HID或Mass Storage等裝置,如此一來就不用安裝Driver這樣麻煩的事。
個人覺得檔案系統是一個最容易呈現的界面。
新元素加入,再來就是市場變化。等著看時代改變了。
2013年5月24日 星期五
X86式微,已經回不來了
一看規格:四核心、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函式庫支援之可能性
作業系統相關
<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日 星期三
如何產生任意大小的磁碟影像
也是Bee第一次在MCU上使用到64位元整數變數。
這種變數數值太大想都沒想過。但遇到檔案系統位址索引就非用不可。
FatFs可以在PC上進行模擬,會產生一個Ram Disk。
不過這個Ram Disk沒有和真實世界相通。
是可以載入SD卡影像檔,但抓取費時。
本想用其他Ram Disk的影像檔來用。結果沒想到Windows有內建。
就在控制台->系統管理工具->電腦管理->磁碟管理
可以在硬碟上產生一個新的碟。
設定上要使用固定大小,不然無法對應真實磁碟。
可以格式化,放入檔案。操作完畢後中斷連接。
再來就可以用檔案讀入的方式Copy進Ram中,給FatFs做為Disk影像用。
2013年5月12日 星期日
從CPU公司併購看科技之發展
Bee一向後知後覺:
Intel賣掉ARM核心一年後才知。
MIPS被Imagination 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行程式,只會編成二個指令,就是4個Byte。
測試寫入檔案的時間是對的,會是編譯的時間。
程式碼:
#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市場鐵律:量變引發質變
意思是當某種型式CPU在市場上佔有數量優勢時,就會形成絶對性優勢。
這和CPU本身品質無關,只因硬體相容性可以讓軟體好好發展。
而要佔有數量,價格不用說一定要夠低,另一種是開放性,非獨家生產。
PC市場因壟斷較看不出來,但MCU卻是很明顯。
8051是8位元MCU的霸主,因為大家都可以做硬體。
16位元來不及有霸主就直接進入32位元MCU時代。
而32位元MCU的霸主正在形成。
硬體統一完畢,再來會變成軟體開始統一。
結果也會有類似的現象,會有統一的軟體架構出現。
又走"量變引發質變"這條路,軟體架構的品質不是重點,而是使用量。
不管軟硬體,使用者習慣才是主導,而市場往使用者多的方向走。
2013年3月16日 星期六
Cortex M4推展不如預期
主因是,要浮點運算做什麼?
往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個指令需要23個Clock執行時間,現在12個指令只要19個Clock執行時間。
用示波器實測,Skip 1000次需時5.02ms,原先為6.80ms,確實加速執行時間。
不過Cortex M3用暫存器變數直接使用int會比short及char來得有效率。中間會少了正負號擴張指令,所以速度會更快。
2013年3月6日 星期三
Cortex-M4開啟新MCU戰場
CM3因為ST已是獨大,所以各廠商就將重心移往CM4。
直到最近TI推展CM4時,才發現價格已經壓到US$3以下。
有浮點運算器的MCU是這樣的價格,等於ADC/DAC不用什麼錢。
其他可以用於浮點運算的應用可以普及。
這樣的轉變,離上次Bee認為32位元MCU變革,只過了剛好一年。
32位元浮點運算,已不是8位元MCU可以做的事。
再下來會大量使用的演算法如:
矩陣運算、傅利葉轉換等等,都會變成非常容易達成。
這樣子MCU程式和PC程式之間差異就更小了。
看來只剩作業系統相容度的問題了。
另一個是使用浮點運算時,可能有效能不足需稍長的時間。
使用作業系統將長時間運算程式做為低優先權的運算,這樣的應用會增多。
RTOS因CM4的出現將會推展的更快。
2013年2月21日 星期四
STM32系列開始支援SDRAM
顯然是要做影像處理的。
再不出Bee都開始考慮轉廠商了。
不過只有網頁型號,沒有多少資料。
這樣Bee就再等數月再看看了。
2013年2月10日 星期日
從PC看MCU發展
PC也是從8位元一路走到64位元。從使用狀況可以推得MCU使用變革。
最早的PC是從8位元的6502開始,當時資源少,組合語言當道。
再來進入8086的16位元PC,C語言開始使用。DOS是最早的作業系統,基本上是單工的時代。資料用電腦處理開始流行。
到了80386,多工作業系統開始使用。PC進入多元發展,主因是32位元已具有處理絶大部分資料的能力。
再來64位元時代開始,一開始還不知要如何用,因為作業系統不支援,應用程式無法發展。可是一但開始支援,大型資料程式就開始發展。
對應於MCU:
8位元MCU是基本型,以目前來看,價格可能是生存唯一的方法。在這個前題下,只能算是可程式化的智慧型裝置。
16位元MCU就是可以處理資料的基本型,有一段時間大約是DSP的領域。基本應用也是單工來得多。
32位元MCU成熟型。同PC一樣,多工的需求來了,也就是RTOS引入各家爭鳴的時代。如同Windows 3.1對OS2的時代一樣。在這個時代要不要使用多工作業系統也引發工程師之間的爭議。但時代的需求是擋不住的。
目前就是處在32位元MCU大量出現的時代。
64位元MCU,應是大量資料處理才會有應用。就觀察何時會開始。
但MCU和PC介面不同,只能由資料的使用量來推估使用領域的變化。
MCU程式設計技巧:示波器的使用
有使用到ADC功能時,示波器是不可缺少的儀器。
但Bee確實看過許多MCU工程師不會用,原因是由軟體轉來的工程師。
不幸的是,信號處理不是單純的軟體。一定要能看到信號才能寫合適的程式。
所以MCU工程師,示波器還是學會如何操作會好些。
除了一般看信號外,好一點的數位示波器可以儲存波型資料由EXCEL來抓取使用。
Bee在一個案例中,就是用數位示波器上所抓取來的資料在EXCEL中就設計出用來取出所要的信號的方法。連程式都還沒有寫就先找出方法,是可以強化程式適應力。
ADC程式設計有一項難處,就是RAM少,不可能將數秒的資料皆存下來,反應快的系統連要使用通信傳輸出來都會是困難。
所以使用數位示波器這一類的外部記錄器將變得很重要。
只要MCU提供一個啟動信號讓數位示波器開始啟動抓取資料,然後儲存下來做分析用,就算是沒有多少RAM的MCU也不用特別去做儲存。再以數位示波器的資料去設計出對應方法就行了。
MCU程式設計技巧:LA的使用
LA:邏輯分析儀
現在低價位USB LA已經很便宜了。
只要是寫MCU通信,都應會使用LA。
雖然Bee也看過有軟體人寫通信記錄器,但LA除了解通信格式外,另一個是有時間記錄。
有了時間記錄,才知道反應時間是否合理。
這個技巧並不是新的,在專業LA就有出現。
但因時代不同,已是人人可以容易取得的工具。
有了新的觀察工具,程式開發就方便多了。
MCU程式設計技巧:中斷及FIFO的使用
能否有效使用中斷,將是MCU程式是否進入專業領域的關鍵。並不是會使用就可以了,而是能否了解工作的時效性並做工作切割。
這也是Bee將中斷及FIFO放在一起的原因。
在一個具有回授性系統上做PID控制。
因為回授控制具有時間敏感度,故不允許時間上的失誤。
其做法是將命令生成做成FIFO,只要FIFO有空間,就填入新的命令。而中斷則只要負責PID回授的計算方程式,以確保用最短時間內做出反應。
類似的工作也出現在通信上面。
應用層程式總是希望通信可以將整個句子一次輸出。但MCU的世界並不是這樣,通信每出一個字都是要花時間的。可以的做法也是使用FIFO,將整個句子用FIFO存起來,再利用中斷接續中間的工作。
能有效的將工作切割、控制好中斷的時效性,那MCU程式設計就開始進入專業等級。
MCU程式設計技巧:Delay的使用
在有作業系統的系統上,Delay不是問題,只要呼叫對的函式就對了。
程式也很好寫,樣子大概就是以下程式:
void Task(void)
{
for(;;)
{
delay(1);
// do something
}
}
只要控制delay的參數,就可以控制執行頻率。
但在無作業系統的MCU上,這可是嚴重的問題。Bee也以如何處理這個問題來看工程師的MCU程式設計的專業程度。
在許多入門書可以看到delay是這樣寫的:
void delay(unsigned int n)
{
while(n--);
}
若是這樣用,就是MCU新鮮人。
因為做為產品,不會只有一項功能,老闆隨時都會加功能,一但功能修改,就會調不完。
有一個變形方法解決在不同MCU上執行的效率差,就是利用Watch Dog計時器去取代delay()中的參數。利用檢查參數值做為時間計數。
另一個問題是:一但在執行delay()其他工作就停擺。
這樣做出來的產品,往往有一個問題,只會做單工,不會處理多重工作。產品特性很挑時序,只能在對的時間送入對的信號,使產品不具適應性。
專業一點的作法,會使用一個Timer做為計時器去改變變數的值,做為計時的檢知。
int delay=DELAY_TIME;
void main(void)
{
while(1)
{
if(delay == 0)
{
// do something
delay=DELAY_TIME;
}
}
}
void Timer_Interrupt(void)
{
if(delay) delay--;
}
這樣做的效果不錯,只是程式有點不太好寫。但可以使不同工作之間較不相互干擾。不過每次加入新的計時器,又要去改寫中斷程式。
這樣做其產品對於多重工作具有近似的反應時間,唯一的問題是工程師要負擔中斷及其他資源管理,也就是無法多人一起開發程式。另外閱讀性稍差,交接需要多花時間去追蹤變數功能。
MCU程式設計技巧:除錯器之使用
JTAG的使用
這是基本技巧,但看到有人不用就寫了MCU數年,還真是驚訝。
雖然在具回授性系統上並不是很好用,但在程式邏輯除錯還是很好用。
不用的結果,就是找不到人可以教。
Bee待過二家公司,都是使用無JTAG及ICE的系統,人員訓練皆難以進行。
主因是程式技術也是由除錯來的,沒有好的觀察器,又如何知高階程式是如何運作。
另外一個問題是,程式發展久了,往往有些特異,就是程式如何運作連設計者也不知,是硬試出來的,更不用說下一個交接者要如何看懂了。
這種特異程式多了,系統往往有怪毛病,造成產品評價不好,也無人可解。
Simulator的使用
這是好的工具才會有的。但因為可用的地方不多,大部分人玩了一下大概不會再玩。
其實會使用還是可以好好使用。
Bee就用在Boot Loader的開發上。
Simulator是無法模擬在現實電路板上的狀況。
但可以自由載入記憶體資料為其特性,也就是可以裝載大量資料,然後看它如何運作。
故Bee就用在Boot Loader載入應用程式的二進制資料,看它的通信寫入是否正常。
因為Boot Loader也不會開太多裝置,所以只用Simulator就寫玩大半。
而且用Simulator也可以將自己的機器碼抓下來,正好做測試用資料。