首先是幾個C語言的學習點。
1.利用一個函數結構體,來保存某一類的函數首地址,一個很好的編程技巧,可以使程序可讀性增加。做法是:
typedef struct {
void (*nand_reset)(void);
void (*wait_idle)(void);
void (*nand_select_chip)(void);
void (*nand_deselect_chip)(void);
void (*write_cmd)(int cmd);
void (*write_addr)(unsigned int addr);
unsigned char (*read_data)(void);
}t_nand_chip;
t_nand_chip nand_chip;
nand_chip.nand_reset=2440_nand_reset;
這裏的結構體成員全都是函數指針,函數指針,顧名思義就是保存函數首地址的指針,可以直接將一個函數名賦值給這個指針。當要調用這個函數時,可以直接像調用函數一樣。
nand_chip.nand_reset(); 注意:這裏其實存在着編譯器的優化,正確的寫法應該是
nand_chip.(*nand_reset)(); nand_reset只是一個指針,它保存的內容纔是函數的首地址,但是編譯器在這裏做了優化,可以使我們代碼編寫簡單,而且好理解。
2.
typedef struct {
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFECC;
} S3C2410_NAND;
static S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
這句話理解了半天,終於想明白了。
關鍵就在於並沒有創建一個新的結構體,而是巧妙的利用了定義結構體的性質。s3c2410這個指針指向的結構體首地址就是0x4e000000,它是NAND寄存器的首地址。它巧妙的把原來已經存在的寄存器組當成了一個結構體,結構體內部的變量都是4字節遞增,正好對應每個寄存器的地址。那麼需要對這個某個寄存器賦值的時候。
volatile unsigned char *p = (volatile unsigned char *) &s3c2410nand->NFSTAT;
這裏的p指針指向的是一個char型空間,所以後面要做強制類型轉換。注意這裏一定不能忘了取地址符&,它才表示這個寄存器的地址。
還有就是在對寄存器操作的時候,最好都用volatile修飾符,不然編譯器可能會對其進行優化。程序中某些處函數沒有使用,個人覺得最好也使用一下。