TQ210 —— 点亮LED
TQ210?—— 點亮LED
?
1、S5PV210?GPIO硬件簡介
1.1、GPIO 【S5PV210有237個多功能IO口,通過設置寄存器確定某個引腳用于輸入輸出或者其他特殊功能】
? ? ? GPIO的英文全稱為General-PurposeIO ports,也就是通用IO接口。在嵌入式系統中常常有數量眾多,但是結構卻比較簡單的外部設備/電路,對這些設備/電路,有的需要CPU為之提供控制手段,有的則需要被CPU用做輸入信號。而且,許多這樣的設備/電路只要求一位,即只要有開/關兩種狀態就夠了。比如,控制某個LED燈亮與滅,或者通過獲取某個引腳的電平屬性來達到判斷外圍設備的狀態。對這些設備/電路的控制,使用傳統的串行口或并行口都不合適。所以在微控制器芯片上一般都會提供一個“通用可編程IO接口”,即GPIO。接口至少有兩個寄存器,即“通用IO控制寄存器”與“通用IO數據寄存器”。數據寄存器的各位都直接引到芯片外部,而對這種寄存器中每一位的作用,即每一位的信號流通方向,則可以通過控制寄存器中對應位獨立地加以設置。比如,可以設置某個引腳的屬性為輸入、輸出或其他特殊功能。 在實際的MCU中,GPIO是有多種形式的。比如,有的數據寄存器可以按照位尋址,有些卻不能按照位尋址,這在編程時就要區分了。比如傳統的8051系列,就區分成可位尋址和不可位尋址兩種寄存器。另外,為了使用的方便,很多MCU的 GPIO接口除必須具備兩個標準寄存器外,還提供上拉寄存器,可以設置IO的輸出模式是高阻,還是帶上拉的電平輸出,或者不帶上拉的電平輸出。這在電路設計中,外圍電路就可以簡化不少。 1.2、特性 ? ? ? 146個可中斷通用控制GPIO;32個可控外部中斷;237個多路復用IO口;睡眠模式引腳狀態可控(除了GPH0/GPH1/GPH2/GPH3)。2、GPIO寄存器
控制S5PV210的GPIO端口寄存器主要有三類:
? ? ? ? 控制寄存器——GPxCON——配置GPIO輸入輸出功能
? ? ? ? 數據寄存器——GPxDAT——設置高低電平
? ? ? ? 上拉寄存器——GPxUP——確定是否使用內部上拉電阻
3、LED原理圖
? ? ? ? 這里兩個NPN三極管,具有放大電流作用,增大驅動能力,只要給基極一個高電平,三極管就可以導通,產生大電流驅動LED點亮。
?
4、匯編點亮LED
? ? ?要點亮LED1,需要配置寄存器GPC0CON的[15:12]為0b0001,使GPC0_3為輸出模式,同時配置寄存器GPC0DAT[3]=1,使GPC0_3引腳輸出高電平。
? ? ?要點亮LED2,需要配置寄存器GPC0CON 的[19:16]為0b0001,使 GPC0_4為輸出模式,同時配置寄存器GPC0DAT[4]=1,使GPC0_4引腳輸出高電平。
? ? ?三個文件:led_on.S? addheader.c ?Makefile
/* led_on.S */ .global _start _start:ldr r0, =0xE0200060 /* GPC0CON寄存器*/ldr r1, =0x00001000 str r1, [r0] /* 設置GPC0_3為輸出,GPC0[15:12]= 0b0001 */ldr r0, =0xE0200064 /* GPC0DAT寄存器*/ldr r1, =0x00000008 str r1, [r0] /* 設置GPC0_3為高電平*/halt:b halt /*死循環*/? ? 為什么需要死循環:CPU 一旦從某個地址運行,它就會從這個地址往后依次取指運行,當運行完我們的代碼,它不會停止,還會往后繼續取指運行,但是后面的指令是未知的,CPU運行后不知道會是什么結果,可能正常執行,也可能出現異常,所以我們應該讓CPU一直在那里死循環。
? ? Makefile:
led_on.bin:led_on.oarm-linux-ld -Ttext 0xD0020010 -oled_on.elf $^arm-linux-objcopy -O binary led_on.elf $@arm-linux-objdump -D led_on.elf >led_on.disled_on.o :led_on.Sarm-linux-gcc -c $< -o $@clean:rm *.o *.elf *.bin *.dis(1)、arm-linux-gcc將start.S編譯成start.o目標文件,-c表示編譯不鏈接,-o跟隨輸出文件名。
(2)、arm-linux-ld 將start.o目標文件鏈接成elf文件格式,-Ttext 0xD0020010表示程序運行的地址是0xD0020010,其實程序可以在任何一個地址運行,因為本源代碼是位置無關碼,后面您會看到可以在內存0x30000000地址運行【TQ210內存:0x20000000~0x40000000】。
(3)、arm-linux-objcopy將ELF格式的可執行文件轉換為二進制文件,即可以在開發板上執行的文件,-O表示指定格式來輸出文件,這里是binary即二進制文件。
(4)、arm-linux-objdump 將ELF文件反匯編,主要用于編譯出錯時,對調試很有幫助,-D表示反匯編所有段。
裸機可以使用SD卡燒和使用 u-boot 菜單欄或者u-boot命令行來燒寫
// 要將led_on.bin燒寫到TQ210中,還需要要添加一個16字節的頭信息。 #include<stdio.h> #include<string.h> #include<stdlib.h>#defineIMG_SIZE 16 * 1024 #defineHEADER_SIZE 16intmain (int argc, char *argv[]) {FILE *fp;unsigned char*buffer;int bufferLen;int nbytes,fileLen;unsigned int checksum, count;int i;if (argc != 3){printf("Usage: %s <sourcefile> <destination file>\n", argv[0]);return -1;}/* 分配16KByte的buffer,BL1最大為16KByte,并初始化為0*/buffer = calloc(1, IMG_SIZE);if (!buffer){perror("Alloc bufferfailed!");return -1;}/* 打開源bin文件*/fp = fopen(argv[1], "rb");if( fp == NULL){perror("source file openerror");free(buffer);return -1;}/* 獲取源bin文件的長度*/fseek(fp, 0L, SEEK_END);fileLen = ftell(fp);fseek(fp, 0L, SEEK_SET);/* 源bin文件不得超過(16K-16)Byte*/if (fileLen > (IMG_SIZE -HEADER_SIZE)){fprintf(stderr, "Source fileis too big(> 16KByte)\n");free(buffer);fclose(fp);}/* 計算校驗和*/i = 0;checksum = 0;while (fread(buffer + HEADER_SIZE + i, 1,1, fp)){checksum += buffer[HEADER_SIZE +i++];}fclose(fp);/* 計算BL1的大小(BL1的大小包括BL1的頭信息),并保存到buffer[0~3]中*/fileLen += HEADER_SIZE;memcpy(buffer, &fileLen, 4);// 將校驗和保存在buffer[8~15]memcpy(buffer + 8, &checksum, 4);/* 打開目標文件*/fp = fopen(argv[2], "wb");if (fp == NULL){perror("destination file openerror");free(buffer);return -1;}// 將buffer拷貝到目標bin文件中nbytes =fwrite(buffer, 1, fileLen, fp);if (nbytes != fileLen){perror("destination filewrite error");free(buffer);fclose(fp);return -1;}free(buffer);fclose(fp);return 0; }首先編譯 addheader.c:gcc addheader.c -o addheader
./addheader led_on.bin 210.bin
將生成的210.bin文件通過SD或者tftp方式下載到TQ210開發板中。
?
5、燒寫裸機程序
(1)、使用SD卡燒寫
dd iflag=dsync oflag=dsync if=210.bin of=/dev/sdb seek=1 表示輸出文件為 210.bin,輸出文件到/dev/sdb,設備文件在 linux 下是 在/dev/目錄下,此時 SD 卡在 Linux 下僅僅被看成是一個文件, seek=1 表示燒寫到扇區 1, Linux 讀寫磁盤設備最小單位是一個扇區。取出SD卡放入TQ210開發板,撥動撥碼開關為SD卡啟動。
注意: /dev/sdb 是查閱 SD在 Linux虛擬機上的設備節點而設置的,如果設備節點為/dev/sdc則需要修改為/dev/sdc,插入 SD卡到 PC 后,在 Linux虛擬機命令行執行 ls /dev/sd*命令查看到設備節點的情況。
?
(2)、使用u-boot菜單欄燒寫
?????? ipaddr:開發板的IP;serverip:Linux的IP【設置好,save保存一下】
?????? tftp 3000000210.bin
?????? go30000000
?
6、用C和匯編混合編程
/* led_on.S*/ .global _start _start:blmain /* 跳轉到C函數去執行*/ halt:bhalt /* 死循環 *//* main.c */ #define GPC0CON *((volatileunsigned int *)0xE0200060) #define GPC0DAT *((volatileunsigned int *)0xE0200064)void delay(volatile unsigned int t) {volatileunsigned int t2 = 0xFFFF;while(t--)for(; t2; t2--); }int main() {int toggle = 0;GPC0CON &= ~(0xFF << 12);GPC0CON |= 0x11 << 12; //配置GPC0_3和GPC0_4為輸出while(1){GPC0DAT &= ~(0x3 << 3); // 熄滅LED1和LED2if(toggle)GPC0DAT|= 1 << 3; // 點亮LED1elseGPC0DAT|= 1 << 4; // 點亮LED2toggle= !toggle;delay(0x50000);}return 0; }? ? 運行 C 語言需要棧,為什么在 led_on.S 中沒有設置棧:S5PV210 上電運行 iROM 中的代碼已經設置好棧,棧頂地址為 0xD0037F80,
總結
以上是生活随笔為你收集整理的TQ210 —— 点亮LED的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql kafka binlog_为
- 下一篇: 【微信小程序】项目实战—抽签应用