1. 程式人生 > >ITOP4412裸機程式設計-串列埠驅動

ITOP4412裸機程式設計-串列埠驅動

文章目錄

前言:

       看過我文章的小夥伴有的可能會有疑問,為什麼用匯編,用C語言不好嗎?我在這裡說明一下,因為後面可能要移植UBoot最新的程式,而UBoot的程式在最初的一段是用匯編寫的,所以我們這裡也用匯編寫,後期移植UBoot就很方便了。燒錄SD的指令碼和第一章點亮LED燈的一樣,這裡不再貼出來了,而是直接用了。

原理分析:

       在STM32微控制器裡,在編寫驅動前做的一件很重要的事情就是時鐘樹配置,這裡串列埠驅動也是,要先配置時鐘樹才能配置串列埠,不然波特率無法計算。
時鐘框架
       從上面圖可以看出,配置時鐘樹要先配置DMC的時鐘,之後在選擇左右匯流排。
時鐘分支
       從上面的圖片可以看出,UART掛載在PERI-L時鐘分支下面。
時鐘樹
       由上面圖可以看出,先配置SCLKmpll時鐘來源,經過鎖相環電路,分頻電路最終到達PERIL,而UART就掛載在這個時鐘分支下面,有的小夥伴會問,那幹嘛配置DMC,請看下圖。
CMU_CORE


       核心的時鐘樹下面藍色部分有個鎖相環,這個鎖相環決定了SCLKmpll時鐘的來源,而前面還有一個MPLL配置電路,不屬於該核心。而鎖相環和DMC在一個時鐘樹中,所以後面需要配置這個鎖相環在DMC相關的暫存器中。這裡還有一個問題,就是FOUTmpll怎麼會配置成的800Mhz,外部時鐘來源是24Mhz的有源晶振。
MPS表
MPLL_CON0
       從上述圖片可以看出來,MPLL_CON0暫存器可以配置FOUT的值,它的值決定於下面的FOUT公式,而這個公式和MPS的設定有關,而從上面MPS表可以查得,P=3,M=100,S=0時FOUT的值就是800了。
       OK!總結一下配置的流程:
先配置MPLL_CON0暫存器讓FOUT的值為800,在配置CLK_SRC_DMC暫存器使鎖相環選定FOUTmpll為時鐘來源,再配置CLK_SRC_TOP1暫存器使MUXmpll_ctrl_user_T鎖相環選定SCLKmpll為時鐘來源,再配置CLK_SRC_PERIL0暫存器使時鐘作用於想用的UART,再配置CLK_DIV_PERIL0暫存器使DIVACLK_100把MPLL的8分頻後作用於對應的UART,時鐘配置到這裡就結束了。之後再設定UART的觸發方式,資料格式,波特率等就簡單了。這裡不再敘述UART的配置方法,根據原始碼去三星的手冊中查暫存器即可。

原始碼:

       新建資料夾及檔案

mkdir uart
cd uart
touch main.S exynos4412.h uart.lds Makefile

       修改main.S

#include "exynos4412.h"
.global _start

.word 0x2000
.word 0x0
.word 0x0
.word 0x0

_start:
   ldr r10, =0x1002330c
   ldr r11, [r10]
   orr r11, r11,#0x300
   str r11, [r10]
       
   ldr r10, =0x11000c08
   ldr r11, =0x0
   str r11, [r10]

   ldr r10, =GPA1CON
   ldr r11, =0x222222
   str r11, [r10]

   ldr r10, =MPLL_CON0
   ldr r11, =0x80640300
   str r11, [r10]

   ldr r10, =CLK_SRC_DMC
   ldr r11, =0x00011000
   str r11, [r10]

   ldr r10, =CLK_SRC_TOP1
   ldr r11, =0x01111000
   str r11, [r10]
   
   ldr r10, =CLK_SRC_PERIL0
   ldr r11, =0x66666
   str r11, [r10]
   
   ldr r10, =CLK_DIV_PERIL0
   ldr r11, =0x777777
   str r11, [r10]

   ldr r10, =UFCON2
   ldr r11, =0x111
   str r11, [r10]

   ldr r10, =ULCON2
   ldr r11, =0x3
   str r11, [r10]
   
   ldr r10, =UCON2
   ldr r11, =0x3c5
   str r11, [r10]
   
   ldr r10, =UBRDIV2
   ldr r11, =0x35
   str r11, [r10]
   
   ldr r10, =UFRACVAL2
   ldr r11, =0x4
   str r11, [r10]
   
   ldr r10, =UTXH2	
   ldr r11, =0x55
   str r11, [r10]
   
   ldr r11, =0x61
   str r11, [r10]
   
   ldr r11, =0x72
   str r11, [r10]
   
   ldr r11, =0x74
   str r11, [r10]
   
   ldr r11, =0xA
   str r11, [r10]
   
   ldr r11, =0xD
   str r11, [r10]

loop:	
   ldr r10, =GPL2CON
   mov r11, #(0x01<<0)
   str r11, [r10]
   ldr r10, =GPL2DAT
   mov r11, #0x01
   str r11, [r10]

   b	loop

       修改exynos4412.h

#ifndef EXYNOS4412_H
#define EXYNOS4412_H

#define GPX1CON (0x11000000+0x0c20)
#define GPX1DAT (0x11000000+0x0c24)
#define GPX1PUD (0x11000000+0x0c28)
#define GPX1DRV (0x11000000+0x0c2c)

#define GPK1CON (0x11000000+0x0060)
#define GPK1DAT (0x11000000+0x0064)
#define GPK1PUD (0x11000000+0x0068)
#define GPK1DRV (0x11000000+0x006c)

#define GPL2CON (0x11000000+0x0100)
#define GPL2DAT (0x11000000+0x0104)
#define GPL2PUD (0x11000000+0x0108)
#define GPL2DRV (0x11000000+0x010c)


//uart
// GPIO
#define GPA1CON (0x11400020)
// MPLL
#define MPLL_CON0 (0x10040108)
#define CLK_SRC_DMC (0x10040200)
#define CLK_SRC_TOP1 (0x1003C214)
// system clock
#define CLK_SRC_PERIL0 (0x1003C250)
#define CLK_DIV_PERIL0 (0x1003C550)
// UART
#define UFCON2 (0x13820008)
#define ULCON2 (0x13820000)
#define UCON2 (0x13820004)
#define UBRDIV2 (0x13820028)
#define UFRACVAL2 (0x1382002c)
#define UTXH2 (0x13820020)
#define URXH2 (0x13820024)

#define UTRSTAT2 (0x13820010)

#endif

       修改Makefile

CROSS_COMPILE = arm-linux-gnueabihf-
%.o : %.S
	$(CROSS_COMPILE)gcc -o [email protected] $< -c

%.o : %.c
	$(CROSS_COMPILE)gcc -o [email protected] $< -c

.PHONY: all
all :	uart.elf

uart.elf : main.o uart.lds
	$(CROSS_COMPILE)ld -T uart.lds -o uart.elf $^
	$(CROSS_COMPILE)objcopy -O binary uart.elf uart.bin
	$(CROSS_COMPILE)objdump -D uart.elf > uart.dis

.PHONY : clean
clean:
	rm -rf *.o *.elf *.bin *.dis

       修改uart.lds

SECTIONS
{
	. = 0x02023400;
	.text : {
		main.o
		* (.text)
	}
	.rodata ALIGN(4) : {
		* (.rodata*)
	}
	
	.data ALIGN(4) : {
		* (.data*)
	}
	.bss ALIGN(4) : {
		* (.bss)
		* (COMMON)
	}
}

修改完上訴檔案使用指令make生成uart.bin下面要用到

燒錄SD卡:

我這裡的SD卡的裝置節點是sdb,請根據自己的實際情況改正後燒錄

cd sd_fuse/itop4412
./sd_fusing.sh /dev/sdb ../../uart.bin

現象:

       這裡現象就不發圖片了,現象就是連線串列埠之後,串列埠助手會顯示Uart四個字母,開發板有一個LED燈亮。如果有疑問,請加群討論。

原始碼獲取:

可以加入群聊:667039215找群主獲取
CSDN獲取:uart壓縮包
github下載:git clone https://github.com/HOU1354696096/ITOP4412.git