顯示具有 單晶片 標籤的文章。 顯示所有文章
顯示具有 單晶片 標籤的文章。 顯示所有文章

2012年1月16日 星期一

單晶片一些相關的用法

指標:
[ 定義 ]
一個變數,用來存放變數位址。

[ 宣告方式 ]
1.
int i = 100;
int *ptr = &i; //宣告ptr為指標,存入i的位址

2.
int i = 100;
int * ptr; //宣告ptr為指標
ptr = &i; //存入i的位址。不可以寫成*ptr = &i
函式型態的別名:
很多寫 C/C++ 的人都把 typedef 當成#define 來使用。
誠然,像這樣的定義
typedef unsigned short WORD;
就相當於
#define WORD unsigned short
但就本義來說,#define 是字串的取代,例如
#define WORD Hello!
在程式任何使用到 WORD 的地方會用 Hello! 取代 WORD

typedef看來不怎麼有用是吧!?非也,由於所謂 C/C++ 的型態是很廣義的,使用typedef
可以使程式看起來簡潔易懂且不容易出錯。下面是幾個typedef的應用例子:

簡單型態的別名
typedef unsigned char BYTE;//定義無號單字節的型態
typedef unsigned short WORD;//定義無號雙字節的型態
typedef unsigned long DWORD;//定義無號四字節的型態
//嗯!這三行沒什麼大不了,用#define也可以做

結構型態的別名
typedef struct StructTag{
int mA;
int mB;
}STRUCTTAG, *PSTRUCTTAG;
當要建立這個結構的物件時,就可以用別名 STRUCTTAG 和 PSTRUCTTAG,例如
STRUCTTAG StructObj;
PSTRUCTTAG pStructObj;
就相當於
struct StructTag StructObj;
struct StructTag *pStructObj;

函式型態的別名
如果你有一個 library 提供了字串轉整數的函式
int HexToInt(char *str);//十六進位字串轉整數
int DecToInt(char *str);//十進位字串轉整數
當你的程式要使用這些函式時,就必需include這些函式的定義,但用typedef會
更簡潔:
typedef int ToInt(char *str);
//上面這行定義了一個需傳入字串(char *)且返回整數(int)的函式型態別名
//叫 ToInt
ToInt HexToInt,DecToInt;//宣告HexToInt,DecToInt這兩個函式
現在你的程式可以呼叫HexToInt(...),DecToInt(...)了。

在Windows,通常是應用程式呼叫API來工作的,但由於某種需求,Windows API
會反過來呼叫應用程式的函式,這種函式稱之為 callback function
callback function 對API來說只有該傳入那些參數和返回值型態,沒有函式名稱而用函式
指標來呼叫(事實上Windows也不可能用程式的函式名稱來呼叫)。這時使用函式型態的別名
來宣告函式指標就特別好用了。
舉個例子吧!建立一個新的行程(Thread)的函式:
CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc,
LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT
nStackSize = 0, DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );

其中AFX_THREADPROC就是一個函式型態的別名
它的定義是
typedef UINT (AFX_CDECL *AFX_THREADPROC)(LPVOID);
//AFX_THREADPROC 是一個傳入一個指標參數返回UINT型態值的函式
//指標的名稱(AFX_CDEL是標明函式呼叫為 __cdecl(C style calling convention))

用這個宣告,不論API或應用程式本身都很方便,如應用程式可以這樣來
開啟行程:
CWinThread* pMyThread=AfxBeginThread(
(AFX_THREADPROC)MyThreadFunc,............
是不是很簡潔明瞭?嗯...MyThreadFunc算不算 callback function 有點疑義,但做為 typedef 的使用例子應沒問題的

typedef :

將資料型態定義成自己希望的識別字,方便撰寫程式.

比方說

typedef int number; // 表示number識別字和int相同.
int n; // 宣告一個int變數n.
number n; // 宣告一個number變數n,而number其實就是int.

又比方說有一個結構叫做record

struct record
{
int number;
struct record *next;
}

typedef struct record Node; // 表示Node識別字和struct record相同.

struct record record1; // 宣告一個record結構名為record1.

Node record1; // 宣告一個Node 結構名為record1,而Node 其實就是 struct record的意思.

除了省下了打字的力氣以外,由於不同的機器使用的資料型態都不太一樣,換機器跑程式時,只要修改typedef就好了,增加了C的可攜性.

[ 參考 ] http://home.educities.edu.tw/peterhuang1/Clan/CLanTypedef.htm

2.
struct t_Point
{
int x; int y;
}; // 注意,這裡最後一個分號不能省略

int main(int argc, char* argv[])
{
struct t_Point a, b;
// . . .
return 0;
}

顯然,這種方法沒有typedef更加直觀(在C++中,main函數第一行的struct關鍵字可以省略,但在標準C中,省略該關鍵字會出現編譯錯誤)。

此外,對於定義鏈接隊列中的結點,我們可以這樣實現:

typedef struct t_node
{
int Value;
struct t_node *next;
} Node;

當然也可以這樣定義:

typedef strcut t_node Node;
struct t_node
{
int Value;
Node *next;
};

結構中的冒號; 位域 :

位域
  有些信息在存儲時,並不需要佔用一個完整的字節, 而只需占幾個或一個二進制位。例如在存放一個開關量時,只有0和1 兩種狀態, 用一位二進位即可。為了節省存儲空間,並使處理簡便,C語言又提供了一種數據結構,稱為「位域」或「位段」。所謂「位域」是把一個字節中的二進位劃分為幾個不同的區域, 並說明每個區域的位數。每個域有一個域名,允許在程序中按域名進行操作。 這樣就可以把幾個不同的對象用一個字節的二進制位域來表示。一、位域的定義和位域變量的說明位域定義與結構定義相仿,其形式為:

  struct 位域結構名

  { 位域列表 };

  其中位域列表的形式為: 類型說明符 位域名:位域長度

  例如:

struct bs
{
 int a:8;
 int b:2;
 int c:6;
};


  位域變量的說明與結構變量說明的方式相同。 可採用先定義後說明,同時定義說明或者直接說明這三種方式。例如:

struct bs
{
 int a:8;
 int b:2;
 int c:6;
}data;


  說明data為bs變量,共佔兩個字節。其中位域a占8位,位域b占2位,位域c占6位。對於位域的定義尚有以下幾點說明:

  1. 一個位域必須存儲在同一個字節中,不能跨兩個字節。如一個字節所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:

struct bs
{
 unsigned a:4
 unsigned :0
/*空域*/ unsigned b:4 /*從下一單元開始存放*/
 unsigned c:4
}


  在這個位域定義中,a佔第一字節的4位,後4位填0表示不使用,b從第二字節開始,佔用4位,c佔用4位。

  2. 由於位域不允許跨兩個字節,因此位域的長度不能大於一個字節的長度,也就是說不能超過8位二進位。
  3. 位域可以無位域名,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:
struct k
{
 int a:1
 int :2 /*該2位不能使用*/ int b:3
 int c:2
};


  從以上分析可以看出,位域在本質上就是一種結構類型, 不過其成員是按二進位分配的。

  二、位域的使用

  位域的使用和結構成員的使用相同,其一般形式為: 位域變量名·位域名 位域允許用各種格式輸出。

main(){
 struct bs
 {
  unsigned a:1;
  unsigned b:3;
  unsigned c:4;
 } bit,*PBit;
 bit.a=1;
 bit.b=7;
 bit.c=15;
 printf("%d,%d,%d\n",bit.a,bit.b,bit.c);
 PBit=&bit;
 PBit->a=0;
 PBit->b&=3;
 PBit->c=1;
 printf("%d,%d,%d\n",PBit->a,PBit->b,PBit->c);
}

  上例程序中定義了位域結構bs,三個位域為a,b,c。說明了bs類型的變量bit和指向bs類型的指針變量PBit。這表示位域也是可以使用指標的。

  程序的9、10、11三行分別給三個位域賦值。( 應注意賦值不能超過該位域的允許範圍)程序第12行以整型量格式輸出三個域的內容。第13行把位域變量bit的地址送給指針變量PBit。第14行用指針方式給位域a重新賦值,賦為0。第15行使用了復合的位運算符"&=", 該行相當於: PBit->b=PBit->b&3位域b中原有值為7,與3作按位與運算的結果為3(111&011=011,十進制值為3)。同樣,程序第16行中使用了復合位運算"=", 相當於: PBit->c=PBit->c1其結果為15。程序第17行用指針方式輸出了這三個域的值。

單晶片C語言,Volatile使用

轉貼  http://ethanjob.blogspot.com/2007/02/volatile.html

volatile宣告 在C裡面有volatile這個宣告,通常是說這個變數會被外在routine改變, 在kernel裡面通常是指會被interrupt handler(有時就是硬體中斷的routine) 改變值,也就是被非同步的改變的變數。例如 unsigned long vloatile jiffies; jiffies在kernel是時間每次hardware的中斷會來改這個值 在asm裡面是說這個東西compiler時,gcc不要雞婆作optimized,因為 最佳化的結果,compiler會把code按照他想的方法放到記憶體裡, 但是有的code我們需要特定指定他一定要在某個記憶體上, 在kernel裡常有這樣情形發生,我們可以用 __asm__ __volatile__宣告一段assembly的code是不要做最佳化的。 例如cli sti #define disable() __asm__ __volatile__ ("cli"); #define enable() __asm__ __volatile__ ("sti");

[ 例1 ]

Volatile這玩意兒用在單晶片的C語言較多

例如:
Volatile char wait;
void xxx(void)
{
wait=1;
while (wait!=0);
.....
.....
}
void timer0(void) interrupt 1
{
wait=0;
.......
}

xxx()中就是等一個timer中斷才執底下工作.
如果不寫Volatile會被編譯器省略掉.
因為wait=1;何來wait會等於0

[ 例2 ]

volatile sig_atomic_t read_flag = 1;

volatile是一個關鍵字(keyword),用來修飾詞資料型態,與const有對應的關係。
是語言關鍵字的話,就不會出現在標頭檔內的定義。
volatile sig_atomic_t read_flag = 1;
read_flag是一個為sig_atomic_t的資料型態,透過volatile的修飾,說明sig_atomic_t在程式中,可以在任何的時間下被修改 ,
也就是說,你的程式可能同一時間不止一個程序在使用。
可能主程式main在使用的同時,I/O Device或另一個thread也在利用或指定這個read_flag
來透過溝通的作用。

[ 例3 ]

http://www.programmersheaven.com/articles/pathak/article1.htm

[ 參考 ]

http://www.programmersheaven.com/articles/pathak/article1.htm

http://www.blueshop.com.tw/board/show.asp?subcde=BRD20060329085552QSX&fumcde=FUM20050124191259IGD&rplcnt=5

2011年9月2日 星期五

SD card有發現容量變小, 找不到,無法格式化

1.在ubuntu 11.04下的桌面,按右鍵,選擇format,會找到Disk Utility
2.進去後,找到Format Drive==>Format ****** 如果不能Format,請找一下mount Volume把它給unmount,就可以format
3.如果在中間的Volumes 下面的bar沒有看到new volume ,就要再去執行Format Volume
4.再去執行mount volume
5,如果以上是在桌面上看不到磁碟機的話,請到請到請到system==>administration==>Disk Utility,在左邊可以看到SD card, 一樣可以


使用SD card的partition啟動NAND

有測試過的,搞了好久,
1.在ubuntu 11.04 linux下,要先知道SD card掛在哪,請在桌面下按右鍵,選擇format,最上面那行就會跟你說是哪一個,測試看到的是 /dev/sdb1
2.打開終端機,sudo fdisk /dev/sdb    <===sdb 要注意這點,不是sdb1
3.不知道指令請按 "m",  "d"是刪除partition 
                       Command (m for help): d
                        Selected partition 1

   "n",是新增一個partition
   Command (m for help): n
   Command action
   e   extended
   p   primary partition (1-4)
 

   "p"建立主要的partition
   p
    Partition number (1-4): 1   <===要幾個partition

   First cylinder (1-1017, default 1): 50    <=====輸入要劃多大的容量
Last cylinder, +cylinders or +size{K,M,G} (50-1017, default 1017):
Using default value 1017


 4.在將SD card 設定成FAT格式,
    sudo mkfs -t vfat /dev/sdb1    <====注意,這次是有sdb1
5. 在windows xp下測試一下SD card是否能打開,有問題的話,會秀需要格式化
=============================================
6.再到windows xp,打開winhex 程式,把剛剛設定好的SD card 透過USB轉卡放去windows下, 再到winhex下的==>tools==>Open Disk==>在physical media選擇剛剛的SD card===>OK
7.再按2下,Unpartitioned  <===這是剛剛在linux 下設定的空間,就是上面的50
8.在0x00~0x1C0,這段空間就是要把u-boot放進去的地方
9.將0x1C0這一行給記錄下來,這一行是在跟PC說它的容量大小,所以必須要記下來
10.去tools==>Disk Tools==>Clone Disk==>Source,選擇右邊像文件的icon,把要寫到partition的u-boot打開,如果看不到,請打*,   Destination,選擇右邊像磁碟機的icon,指到Physical Media下面的SUB( 就是指SD card),右邊的Copy entire raw image file選項要打勾,start sector要輸入0(零),剩下的不管,就是不打勾==>ok
11.會出現很多的訊息,這些全部都按"確定"
12.在將剛剛所備份的0x1C0那行,回存到當前的0x1C0
13.File==>save    大功靠成
14.將要燒得檔案放入SD card中
15.以上就可以測試燒錄了









2011年7月28日 星期四

將bin檔案放置SD card

1.要先用linux ubuntu format SD card
   sudo fdisk /dev/sdc     =>sdc 這是要看插入sd card是在哪裝置
    輸入後,顯示如下:
WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help):
Command (m for help): m
Command action
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition
   l   list known partition types
   m   print this menu
   n   add a new partition
   o   create a new empty DOS partition table
   p   print the partition table
   q   quit without saving changes
   s   create a new empty Sun disklabel
   t   change a partition's system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit
   x   extra functionality (experts only)

Command (m for help): d
Partition number (1-4): 1

Command (m for help): n
Command action寫最後面的數字
   p   primary partition (1-4)
p
Selected partition 1
First cylinder (1-1015, default 1): 50     <== 50 是要寫入檔案的大小
Last cylinder, +cylinders or +size{K,M,G} (50-1015, default 1015): 1015   <= 50-1015 寫最後面的數字

Command (m for help): w
The partition table has been altered!


上面是我操作的指令

sudo mkfs -t vfat /dev/sdd       <==更改為fat format
最後到windows xp上格式化就好了
完成 !!!!!