天天看點

OK6410序列槽裸闆程式uart0

開發環境

系統:ubuntu 10.04.4

單闆:ok6410

編譯器:arm-linux-gcc-4.3.2

搭建開發環境詳見ubuntu 10.04.4開發環境配置。

目标:實作ok6410 uart0 顯示任意輸入字元

一、編寫源代碼

根據s3c6410手冊編寫代碼,包括源檔案start.S clock.S main.c uart.c uart.h lib.c lib.h Makefile

檔案start.S:

.globl _start
_start:

/* 硬體相關的設定 */
    /* Peri port setup */
    ldr r0, =0x70000000
    orr r0, r0, #0x13
    mcr p15,0,r0,c15,c2,4       @ 256M(0x70000000-0x7fffffff)
    
/* 關看門狗 */
/* 往WTCON(0x7E004000)寫0 */
	
	ldr r0, =0x7E004000
	mov r1, #0
	str r1, [r0]
	
	/* 設定棧 */
	ldr sp, =8*1024

	/* 設定時鐘 */
	bl clock_init

	bl main
halt:
	b halt	
           

檔案clock.S:

.globl clock_init

clock_init:
	
	/* 1.設定LOCK_TIME */
	ldr r0, =0x7E00F000  /* APLL_LOCK */
	ldr r1, =0x0000FFFF
	str r1, [r0]
	
	str r1, [r0, #4]	 /* MPLL_LOCK */
	str r1, [r0, #8]	 /* EPLL_LOCK */	
	
#define OTHERS		0x7e00f900
	@ set async mode  /* 當CPU時鐘 != HCLK時,要設為異步模式 */
	ldr r0, =OTHERS
	ldr r1, [r0]
	bic r1, #0xc0			
	str r1, [r0]

loop1:				/* 等待,直到CPU進入異步模式 */
	ldr r0, =OTHERS
	ldr r1, [r0]
	and r1, #0xf00					
	cmp r1, #0
	bne loop1		
	
	/* SYNC667 */
	/* MISC_CON[19] = 0 */

#define ARM_RATIO    0   /* ARMCLK = DOUTAPLL / (ARM_RATIO + 1)    */
#define HCLKX2_RATIO 1   /* HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) */
#define HCLK_RATIO   1   /* HCLK = HCLKX2 / (HCLK_RATIO + 1)       */
#define PCLK_RATIO   3   /* PCLK   = HCLKX2 / (PCLK_RATIO + 1)     */
#define MPLL_RATIO   0   /* DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1)     */
	ldr r0, =0x7E00F020  /* CLK_DIV0 */
	ldr r1, =(ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12)
	str r1, [r0]
	
	/* 2.配置時鐘 */
	/* 2.1 配置APLL */
	/* 2.1.1 設定APLL
	 * 2.1.2 MUXAPLL
	 * 2.1.3 SYNC667
	 * 2.1.4 DIVAPLL
	 */
#define APLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
	ldr r0, =0x7E00F00C
	ldr r1, =APLL_CON_VAL
	str r1, [r0]		/* APLL_CON, FOUTAPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz  */
	
	/* 2.2 配置MPLL */
	/* 2.2.1 設定MPLL
	 * 2.2.2 MUXMPLL
	 * 2.2.3 SYNCMUX
	 * 2.2.4 SYNC667
	 * 2.2.5 HCLKX2_RATIO
	 * 2.2.6 PCLK_RATIO
	 */
#define MPLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
	ldr r0, =0x7E00F010
	ldr r1, =MPLL_CON_VAL
	str r1, [r0]		/* MPLL_CON, FOUTMPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz  */
	
	/* 3.選擇PLL的輸出作為時鐘源 */
	ldr r0, =0x7E00F01C
	ldr r1, =0x03
	str r1, [r0]
	
	mov pc, lr
           

檔案main.c:

#include "uart.h"
#include "lib.h"

int main()
{
	char c;
	
	uart_init();
  	while(1)
    	{
        // 從序列槽接收資料後,判斷其是否數字或子母,若是則加1後輸出
 	do {
		c = getc();
		if (c == '\n' || c == '\r')
		  {
		   	putc('\n');
			putc('\r');
		  }
		else
		  {
		   	 putc(c);
		  }

      	} while (c == '\n' || c == '\r');
   	}
	
	return 0;
}
           

檔案uart.c:

#define ULCON0     (*((volatile unsigned long *)0x7F005000))
#define UCON0      (*((volatile unsigned long *)0x7F005004))
#define UFCON0     (*((volatile unsigned long *)0x7F005008))
#define UMCON0     (*((volatile unsigned long *)0x7F00500C))
#define UTRSTAT0   (*((volatile unsigned long *)0x7F005010))
#define UFSTAT0    (*((volatile unsigned long *)0x7F005018))
#define UTXH0      (*((volatile unsigned char *)0x7F005020))
#define URXH0      (*((volatile unsigned char *)0x7F005024))
#define UBRDIV0    (*((volatile unsigned short *)0x7F005028))
#define UDIVSLOT0  (*((volatile unsigned short *)0x7F00502C))

#define GPACON     (*((volatile unsigned long *)0x7F008000))


void uart_init(void)
{
	GPACON &= ~0xff;
	GPACON |= 0x22;
	
	/* ULCON0 */
	ULCON0 = 0x3;  /* 資料位:8, 無較驗, 停止位: 1, 8n1 */
	UCON0  = 0x5;  /* 使能UART發送、接收 */
	UFCON0 = 0x01; /* FIFO ENABLE */

	UMCON0 = 0;
	
	/* 波特率 */
	/* DIV_VAL = (PCLK / (bps x 16 ) ) - 1 
	 * bps = 57600
	 * DIV_VAL = (66500000 / (115200 x 16 ) ) - 1 
	 *         = 35.08
	 */
	UBRDIV0   = 35;

	/* x/16 = 0.08
	 * x = 1
	 */
	UDIVSLOT0 = 0x1;
	
}
           

檔案uart.h:

void uart_init(void);
           

檔案lib.c:

#define UFSTAT0    (*((volatile unsigned long *)0x7F005018))
#define UTXH0      (*((volatile unsigned char *)0x7F005020))
#define URXH0      (*((volatile unsigned char *)0x7F005024))

char getc(void)
{
	while ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0);
	return URXH0;
}

void putc(char c)
{
	while (UFSTAT0 & (1<<14));
	UTXH0 = c;
}
           

檔案lib.h:

void putc(char c);
char getc(void);
           

檔案Makefile:

2_uart.bin: start.o clock.o main.o uart.o lib.o
	arm-linux-ld -Ttext 0x52000000 -o uart.elf $^
	arm-linux-objcopy -O binary uart.elf 2_uart.bin
	arm-linux-objdump -D uart.elf > uart.dis

%.o : %.S
	arm-linux-gcc -o $@ $< -c

%.o : %.c
	arm-linux-gcc -o $@ $< -c

clean:
	rm *.o uart.elf *.bin uart.dis
           

二、編譯

編譯後将生成的2_uart.bin拷到ubuntu 的tftp目錄下,tftp配置詳見ubuntu 10.04.4開發環境配置

[email protected]:~$ cd Si/OK6410/2_uart0/

[email protected]:~/Si/OK6410/2_uart0$ ls

clock.S  lib.c  lib.h  main.c  Makefile  start.S  uart.c  uart.h

[email protected]:~/Si/OK6410/2_uart0$ make

arm-linux-gcc -o start.o start.S -c

arm-linux-gcc -o clock.o clock.S -c

arm-linux-gcc -o main.o main.c -c

In file included from main.c:3:

lib.h:1: warning: conflicting types for built-in function 'putc'

arm-linux-gcc -o uart.o uart.c -c

arm-linux-gcc -o lib.o lib.c -c

lib.c:12: warning: conflicting types for built-in function 'putc'

arm-linux-ld -Ttext 0x52000000 -o uart.elf start.o clock.o main.o uart.o lib.o

arm-linux-objcopy -O binary uart.elf 2_uart.bin

arm-linux-objdump -D uart.elf > uart.dis

[email protected]:~/Si/OK6410/2_uart0$ ls

2_uart.bin  clock.S  lib.h  main.c  Makefile  start.S  uart.dis  uart.h

clock.o     lib.c    lib.o  main.o  start.o   uart.c   uart.elf  uart.o

[email protected]:~/Si/OK6410/2_uart0$ cp 2_uart.bin /home/change/work/tftpboot/

三、燒寫測試

我的單闆ok6410中有NAND flash,沒有NOR flash。考慮到大多數電腦沒有并口,也沒有程式設計器,我用u-boot下載下傳程式到記憶體運作。但是單闆的u-boot要支援網卡。

以後會寫一個操作NAND的自我更新程式的,到時下載下傳程式就友善了。

單闆上電:

U-Boot 2012.04.01 (Jan 11 2013 - 14:47:24) for SMDK6410

CPU:     [email protected]

         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode) 

Board:   SMDK6410

DRAM:  128 MiB

WARNING: Caches not enabled

Flash: 0 KB

NAND:  select s3c_nand_oob_mlc_64

id_data[0] = 0xec id_data[1] = 0xd5 id_data[2] = 0x94 id_data[3] = 0x29 id_data[4] = 0x34 id_data[5] = 0x41 id_data[6] = 0xec id_data[7] = 0xd5 NAND_ECC_NONE selected by board driver. This is not recommended !!

2048 MiB

realpage value:255

page value:255

ret value:0

In:    serial

Out:   serial

Err:   serial

Net:   dm9000

Hit any key to stop autoboot:  0 

##### 100ask Bootloader for OpenJTAG #####

[n] Download u-boot to Nand Flash

[k] Download Linux kernel uImage

[j] Download root_jffs2 image

[y] Download root_yaffs image

[d] Download to SDRAM & Run

[z] Download zImage into RAM

[g] get file, and write to nand flash 0 block

[f] Format the Nand Flash

[s] Set the boot parameters

[b] Boot the system

[r] Reboot u-boot

[q] Quit from menu

Enter your selection: q

SMDK6410 # printenv

baudrate=115200

bootargs=console=ttySAC0,115200 root=/dev/mtdblock3

bootcmd=nand read 0x50000000 0x60000 0x200000;bootm 0x50000000

bootdelay=5

ethact=dm9000

ethaddr=00:0c:29:4d:e4:f4

gatewayip=172.16.1.1

ipaddr=172.16.1.133

netmask=255.255.255.0

serverip=172.16.1.135

stderr=serial

stdin=serial

stdout=serial

Environment size: 336/524284 bytes

SMDK6410 # ping 172.16.1.135

dm9000 i/o: 0x18000000, id: 0x90000a46 

DM9000: running in 16 bit mode

MAC: 00:0c:29:4d:e4:f4

operating at 100M full duplex mode

Using dm9000 device

host 172.16.1.135 is alive

SMDK6410 # tftp 0x52000000 2_uart.bin

dm9000 i/o: 0x18000000, id: 0x90000a46 

DM9000: running in 16 bit mode

MAC: 00:0c:29:4d:e4:f4

operating at 100M full duplex mode

Using dm9000 device

TFTP from server 172.16.1.135; our IP address is 172.16.1.133

Filename '2_uart.bin'.

Load address: 0x52000000

Loading: #

done

Bytes transferred = 664 (298 hex)

下面開始測試uart程式,在u-boot輸入指令go 0x52000000,程式便開始運作,并且是一去不複返

SMDK6410 # go 0x52000000

## Starting application at 0x52000000 ...

此時輸入任意字元,測試OK

adfsdQWDF

midfakd3148

ok6410 test

it's ok!

繼續閱讀