linux驅動學習筆記---s5pv210(一)
1,解壓核心原始碼
tar -xvf linux-3.0.8.tar.bz2
2,核心的編譯步驟:
a,設定交叉工具鏈--目標檔案執行在arm處理上, 修改Makefile
195 ARCH ?= arm
196 CROSS_COMPILE ?= arm-none-linux-gnueabi-
b,選擇當前開發的soc:核心原始碼相容性比較強:s3c2410, s3c6410, s5pv210
make s5pv210_defconfig // 原理: arch/arm/configs/s5pv210_defconfig ==》拷貝到當前目錄: .config (控制原始碼編譯)
c, 進一步選擇核心模組(裁剪) //如果出現編譯報錯,需要安裝'make menuconfig' requires the ncurses libraries.
//解決: sudo apt-get install libncurses5-dev
make menuconfig //產生一個圖形介面,選擇自己需要的東西
d, make zImage -j2 //編譯核心. -j2表示雙執行緒編譯
最原始的核心是不能直接執行成功, 需要做移植:
D:\Linux驅動課程-fs210_1804\驅動參考程式碼和資料\1st_搭建環境\實驗\系統環境搭建移植文件.doc
編譯完成之後:自動生成
arch/arm/boot/zImage
3, 啟動核心:
cp arch/arm/boot/zImage /tftpboot
uboot設定:
FS210 # set bootcmd tftp 0x40008000 zImage \; bootm 0x40008000
// bootcmd變數作用: uboot倒計時自動要做的事情
FS210 # save
4, 掛載根檔案系統
D:\Linux驅動課程-fs210_1804\source\rootfs_fs210.tgz ==》 /opt
Ubuntu中配置
sudo tar -xvf rootfs_fs210.tgz ==> /opt/rootfs
配置nfs伺服器:
sudo vim /etc/exports
/opt/rootfs *(subtree_check,rw,no_root_squash,async)
重啟nfs伺服器:
sudo service nfs-kernel-server restart
uboot配置:bootargs: uboot傳遞給核心的引數,告訴核心掛載哪裡的根檔案系統
FS210 # set bootargs root=/dev/nfs nfsroot=192.168.7.108:/opt/rootfs_fs210 ip=192.168.7.168 console=ttySAC0,115200 init=/linuxrc
FS210 # save
// root=/dev/nfs /dev/nfs只是一個字串,核心需要通過nfs掛載根系統
// nfsroot=192.168.7.3:/opt/rootfs : 指定掛載機器的ip和路徑, 路徑一定要和/etc/exports中的路徑保持一致
//console=ttySAC0,115200 : 指定串列埠com1,波特率
//init=/linuxrc :指定祖先程序--init程序
====================================================================================================
編寫驅動程式碼
// 1, 新增標頭檔案
#include <linux/init.h>
#include <linux/module.h>
// 3,實現驅動模組載入/解除安裝入口函式
static int hello_drv_init(void)
{
printk("--------^_* %s-------\n", __FUNCTION__);
return 0;
}
static void hello_drv_exit(void)
{
printk("--------^_* %s-------\n", __FUCNTION__);
}
// 2,宣告驅動模組載入/解除安裝入口函式
module_init(hello_drv_init);
module_exit(hello_drv_exit);
// 4, 新增gpl認證
MODULE_LICENSE("GPL");
============================================================================
Makefile的寫法:
#指定核心所在路徑
KERNEL_DIR = /home/farsight/s5pv210/kernel/linux-3.0.8
#獲取當前路徑
CURRENT_DIR = $(shell pwd)
all:
#進入到核心原始碼中,執行核心Makefile, 告訴核心將當前目錄中的原始碼編譯成模組
make -C $(KERNEL_DIR) M=$(CURRENT_DIR) modules
clean :
make -C $(KERNEL_DIR) M=$(CURRENT_DIR) clean
install:
cp -raf *.ko /opt/rootfs/drv_module
#指定編譯哪個模組
obj-m += hello_drv.o
============================================================================
執行:
[[email protected] /drv_module]# insmod hello_drv.ko
--------^_* hello_drv_init-------
[[email protected] /drv_module]# lsmod
hello_drv 877 0 - Live 0x7f004000
[[email protected] /drv_module]# rmmod hello_drv
--------^_* hello_drv_exit-------
=====================================================
編寫驅動程式碼的時候,不會用vim去編寫, 一般都是用source insight
1, 解壓核心原始碼--windows某個位置
2, 將D:\Linux驅動課程-fs210_1804\source\si_linux308-ori.tgz,解壓到核心linux3.0.8原始碼目錄下
3,開啟linux308-ori.PR
申請裝置號:
// 引數1---指定的主裝置號--就是一個整數,選255以上
//引數2--裝置的描述--自定義的字串
//引數3--裝置驅動的檔案操作物件
//返回值: 錯誤為負數,正確為0
ret = register_chrdev(dev_major, "hello_device", &hello_fops);
登出裝置號:
// 引數1---指定的主裝置號--就是一個整數,選255以上
//引數2--裝置的描述--自定義的字串
unregister_chrdev(dev_major, "hello_device");
[[email protected] /drv_module]# cat /proc/devices
Character devices:
1 mem
2 pty
3 ttyp
4 /dev/vc/0
4 tty
4 ttyS
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
265 hello_device
ARM時鐘
c語言與彙編交叉程式碼
.text
.global _start
_start:
@ init sp c函式中有棧的概念,彙編程式碼在呼叫c中的函式時,需要初始化棧才能使用,棧指標是從上往下走的,bl led_main
ldr sp, =0x30008000
@ pass args
ldr r0, =0x100000
bl led_main
loop:
b loop
#define GPC0CON *((volatile unsigned long *)0xE0200060)
#define GPC0DAT *((volatile unsigned long *)0xE0200064)
int led_main(int delay)
{
// c程式中對led進行控制
// 配置 輸出功能
GPC0CON &= ~(0xff<<12);
GPC0CON |= (0x11<<12);
int i;
while(1)
{
GPC0DAT |= (0x3<<3);
for(i=delay; i>0; i--);
GPC0DAT &= ~(0x3<<3);
for(i=delay; i>0; i--);
}
return 0;
}
ledasm.bin : start.S
arm-none-linux-gnueabi-gcc -c start.S -o start.o
arm-none-linux-gnueabi-gcc -c main.c -o main.o
arm-none-linux-gnueabi-ld -Ttext 0x40008000 start.o main.o -o led_asm.elf
arm-none-linux-gnueabi-objcopy -O binary led_asm.elf ledasm.bin
arm-none-linux-gnueabi-objdump -D led_asm.elf > led.dis
clean:
rm -rf *.o *.elf *.dis *.bin
install:
cp -raf *.bin /tftpboot