1. 程式人生 > >skyeye學習之s3c2410的串列埠通訊

skyeye學習之s3c2410的串列埠通訊

s3c2410手冊 :   http://wenku.baidu.com/view/105ddc264b35eefdc8d3338a.html

http://wenku.baidu.com/view/c5c9171a59eef8c75fbfb3b5.html

s3c2410引腳分類: http://wenku.baidu.com/view/003795f8c8d376eeaeaa3102.html

在網上苦苦尋找skyeye的使用教程,發現根本沒有搜到幾篇文章。即使有,也是說說理論部分,根本不會詳細的說明原始碼如何使用,編譯,連結,生成,對於我這種剛剛接觸skyeye的人來說,要使用skyeye來進行模擬真的非常難啊。故鑑於網上資料少之又少,只好自己硬著頭皮去研究例子和原始碼,至此記錄skyeye的學習。

對skyeye模擬s3c2410引腳,時鐘,串列埠等暫存器的詳細描述,可以看skyeye的原始碼:skyeye/soc/arm/s3c2410x下的s3c2410x.h

由此可以知道skyeye中s3c2410所支援的外設模組有哪些。

S3C2410的UART的暫存器有11X3個(3個UART)之多,我選UART0來進行通訊,用到的暫存器有8個。不過初始化就用去了5個暫存器,剩下的3個用於接收、傳送資料。

第一步:串列埠編寫流程

         1、初始化引腳: 把使用到的引腳GPH2、GPH3定義為TXD0、RXD0

                    GPHCON |= 0xa0 

                    GPHUP |= 0x0c

         2、設定串列埠資料格式暫存器ULCON0:8個數據位,1個停止位,無校驗,正常操作模式(與之相對的是Infra-Red Mode,此模式表示0、1的方式比較特殊)

                    ULCON0  = 0x03

         3、設定串列埠控制暫存器UCON0:設定傳送、接收都使用“中斷或查詢方式”

                    UCON0  = 0x05

         4、設定串列埠FIFO暫存器UFCON0:本次不使用FIFO,設為預設值0 

                   UFCON0 = 0x00

         5、UMCON0 (UART channel 0 Modem control register ):本次不使用流控,設為預設值0 

                   UMCON0 = 0x00

         6、設定波特率暫存器UBRDIV0:波特率計算公式UBRDIVn = (int)(PCLK / (bps x 16) ) –1 ,要看說明書驗算一下此波特率是否在可容忍的誤差範圍之內;如果不在,則需要更換另一個波特率,本次使用的57600是符合的

                   UBRDIV0 = 0x12

至此,串列埠初始化完畢,下面進行資料的收發:

          串列埠狀態暫存器:UTRSTAT0  其位功能如下

         位[2]:無資料傳送時,自動設為1。當我們要使用串列埠傳送資料時,先讀此位以判斷是否有資料正在佔用傳送口。 

         位[1]:傳送FIFO是否為空,本次未用此位 

         位[0]:接收緩衝區是否有資料,若有,此位設為1。需要用到這位,需要不斷查詢此位一判斷是否有資料已經被接收。 

          串列埠傳送暫存器UTXH0 :把要傳送的資料寫入此暫存器。 

3、接收資料: 

        UTRSTAT0:如同上述“傳送資料”所列,我們用到位[0] 

        串列埠傳送暫存器URXH0 : 當查詢到UTRSTAT0 位[0]=1時,讀此暫存器獲得串列埠接收到的資料。

對程式有了大概的流程後,下一步開始編碼:

我的工程的組成:

                            start.s         設定中斷,堆疊環境

                            s3c2410.h   定義暫存器巨集

                            serial.c serial.h 串列埠初始化函式,收發函式

                            hello.c          主要函式

-----------------------------------------------------------------------------------------------------------------------------

 start.s 的程式碼如下

#define MODE_SVC 0x13

#define I_BIT   0x80

.text

.align 4

.global begin

.type begin, function

begin:

/*disable I-bit*/

mov     r0, #I_BIT|MODE_SVC

msr     cpsr_c, r0

mov r1,#0xd2

sub r2,r0,r1

ldr sp, =irq_stack           @ set sp_irq = irq_stack

bl hello

b begin

.data

.align  4

irq_stack:

.space 4096

-----------------------------------------------------------------------------------------------------------------------------

s3c2410.h的程式碼如下

/* WOTCH DOG register */

#define WTCON (*(volatile unsigned long *)0x53000000)

/* SDRAM regisers */

#define MEM_CTL_BASE 0x48000000

#define SDRAM_BASE 0x30000000

/* NAND Flash registers */

#define NFCONF (*(volatile unsigned int  *)0x4e000000)

#define NFCMD (*(volatile unsigned char *)0x4e000004)

#define NFADDR (*(volatile unsigned char *)0x4e000008)

#define NFDATA (*(volatile unsigned char *)0x4e00000c)

#define NFSTAT (*(volatile unsigned char *)0x4e000010)

/*GPIO registers*/

#define GPBCON (*(volatile unsigned long *)0x56000010)

#define GPBDAT (*(volatile unsigned long *)0x56000014)

#define GPHCON (*(volatile unsigned long *)0x56000070)

#define GPHDAT (*(volatile unsigned long *)0x56000074)

#define GPHUP (*(volatile unsigned long *)0x56000078)

/*UART registers*/

#define ULCON0 (*(volatile unsigned long *)0x50000000)

#define UCON0 (*(volatile unsigned long *)0x50000004)

#define UFCON0 (*(volatile unsigned long *)0x50000008)

#define UMCON0 (*(volatile unsigned long *)0x5000000c)

#define UTRSTAT0 (*(volatile unsigned long *)0x50000010)

#define UTXH0 (*(volatile unsigned char *)0x50000020)

#define URXH0 (*(volatile unsigned char *)0x50000024)

#define UBRDIV0 (*(volatile unsigned long *)0x50000028)

-----------------------------------------------------------------------------------------------------------------------------

serial.h的程式碼如下void init_uart(void);void putc(unsigned char c);unsigned char getc(void);

-----------------------------------------------------------------------------------------------------------------------------

serial.c的程式碼如下#include "s3c2410.h"#include "serial.h"
#defineTXD0READY(1<<2)#defineRXD0READY(1)
void init_uart( ){//初始化UART        GPHCON |= 0xa0;//GPH2,GPH3 used as TXD0,RXD0        GPHUP = 0x0c;//GPH2,GPH3內部上拉
        ULCON0 = 0x03;//8N1        UCON0 = 0x05;//查詢方式        UFCON0 = 0x00;//不使用FIFO        UMCON0 = 0x00;//不使用流控        UBRDIV0 = 12;//波特率為57600}
void putc(unsigned char c){        while( ! (UTRSTAT0 & TXD0READY) );        UTXH0 = c;}
unsigned char getc( ){        while( ! (UTRSTAT0 & RXD0READY) );        return URXH0;}

-----------------------------------------------------------------------------------------------------------------------------

hello.c的程式碼如下

#include "s3c2410.h"

#include "serial.h"

#define BOGO_MIPS 1000000

void hello(void)

{

int i;

char * hellostr="helloworld";

int timeout ;

i = *hellostr - 'h';

init_uart();

while(1){

timeout = 0;

while(++timeout != BOGO_MIPS);

for(i=0;i<10;i++)

{

putc(hellostr[i]);

}

}

return;

}

-----------------------------------------------------------------------------------------------------------------------------接下來就是要寫連結檔案了,它決定檔案的儲存域,載入域,允許域等東西,是合併檔案所需要的下面就是hello.lds的類容了,具體含義上網看看lds連結檔案的含義吧OUTPUT_ARCH(arm)ENTRY(begin)SECTIONS{ . = 0xc0000000; .text :  { *(.text)  *(.rodata) }

. = ALIGN(8192);
.data : {*(.data)}
.bss : {*(.bss)}

        /* Stabs debugging sections.    */        .stab 0 : { *(.stab) }        .stabstr 0 : { *(.stabstr) }        .stab.excl 0 : { *(.stab.excl) }        .stab.exclstr 0 : { *(.stab.exclstr) }        .stab.index 0 : { *(.stab.index) }        .stab.indexstr 0 : { *(.stab.indexstr) }        .comment 0 : { *(.comment) }        .debug_abbrev 0 : { *(.debug_abbrev) }        .debug_info 0 : { *(.debug_info) }        .debug_line 0 : { *(.debug_line) }        .debug_pubnames 0 : { *(.debug_pubnames) }        .debug_aranges 0 : { *(.debug_aranges) }
}

-----------------------------------------------------------------------------------------------------------------------------

接下來就是寫個Makefile檔案,最終生成我們的目標檔案

下面是我寫的Makefile的內容了

#begin

    CC=arm-elf-gcc

    LD=arm-elf-ld

    CFLAGS= -c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -pipe -g -mapcs-32 -march=armv4 -mtune=arm7tdmi 

    LDFLAGS= -N -p -X -Thello.lds

    LIB=

    all: hello 

    hello: start.o hello.o serial.o 

$(LD) $(LDFLAGS)  start.o hello.o serial.o -o hello

arm-elf-objdump -xS hello > hello.s 

arm-elf-readelf -a hello > hello.r

arm-elf-nm hello > hello.n

    start.o:start.S

$(CC) $(CFLAGS) start.S

    hello.o:hello.c

$(CC) $(CFLAGS) hello.c

    serial.o:serial.c

$(CC) $(CFLAGS) serial.c

    clean:

rm -rf *.o *.elf *.gdb *.r *.n *.s

    test:

skyeye -e hello -c skyeye.conf

#end

---------------------------------------------------------------------------------------

Makefile的基本語法過程也應該會點吧,不會的話就應該自己補補了

最後就是skyeye的skyeye.conf的檔案置配了

關於skyeye.conf裡面的內容介紹,請看skyeye的官方PDF文件,裡面說的很清楚

在這裡需要設定記憶體的分佈圖,外設IO,cpu體系結構等,下面是我的skyeye.conf檔案的置配內容

#skyeye config file sample

cpu:  arm920t

mach: s3c2410x

#physical memory  

#mem_bank: map=M, type=RW, addr=0x01000000, size=0x00400000

#mem_bank: map=M, type=RW, addr=0x20000000, size=0x01000000

mem_bank: map=M, type=RW, addr=0xc0000000, size=0x01000000

mem_bank: map=M, type=RW, addr=0xc1000000, size=0x00600000, file=./initrd.img

mem_bank: map=M, type=RW, addr=0xc1600000, size=0x00a00000

#all peripherals I/O mapping area

#mem_bank: map=I, type=RW, addr=0xfefa0000, size=0x00060000

mem_bank: map=I, type=RW, addr=0x48000000, size=0x20000000

mem_bank: map=I, type=RW, addr=0x19000300, size=0x00000020

uart:mod=term

#net: type=cs8900a, base=0x19000300, size=0x20,int=9, mac=0:4:3:2:1:f, ethmod=tuntap, hostip=10.0.0.1

#lcd:type=s3c2410x,mod=gtk

#dbct:state=on

好了,至此skyey的s3c2410的串列埠編寫的整個流程都搞好了

在工程目錄下終端鍵入make生成

鍵入 make test,自動進入skyeye,然後start,run就可以了

以下是測試通過的圖