CH9434 嵌入式Linux与安卓系统驱动移植和使用教程
Posted PC技术小能手
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CH9434 嵌入式Linux与安卓系统驱动移植和使用教程相关的知识,希望对你有一定的参考价值。
1 前言
CH9434是一款SPI转四串口转接芯片,提供四组全双工的9线异步串口,用于单片机/嵌入式/安卓系统扩展异步串口。提供25路GPIO,以及支持RS485收发控制引脚TNOW。本篇基于STM32MP157处理器平台,介绍CH9434在嵌入式Linux系统/安卓系统的驱动移植和使用方法。
CH9434相关资料下载链接:
CH9434评估板设计原理图,单片机端操作例程,LINUX驱动及应用例程下载
2 驱动移植流程
2.1 移植准备
1、配置系统SPI设备信息,若支持DTS设备树可以直接在DTS文件中直接定义此SPI结构体信息,如下所示:
&spi5
pinctrl-names = "default","sleep";
pinctrl-0 = <&spi5_pins_a>;
pinctrl-1 = <&spi5_sleep_pins_a>;
status = "okay";
cs-gpios = <&gpioz 4 GPIO_ACTIVE_LOW>;
ch9434: ch9434@1
compatible = "wch,ch943x";
reg = <0>;
spi-max-frequency = <3000000>;
interrupt-parent = <&gpiod>;
interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
;
;
对于不支持DTS设备树的系统,则需要在board源文件中定义spi0_board_info对象,如下所示:
static struct spi_board_info spi0_board_info[] __initdata =
.modalias = "ch943x_spi",
.platform_data = NULL,
.max_speed_hz = 3000000,
.bus_num = 0,
.chip_select = 0,
.mode = SPI_MODE_0,
.controller_data = &spi0_csi[0],
.irq = IRQ_EINT(8),
;
2、配置IO中断引脚,确认CH9434芯片INT中断请求引脚所连接的CPU的IO口编号,此IO需支持中断功能。此编号可以直接在驱动源码ch9434.c中直接指定,也可以在如上SPI设备结构体中指定,如步骤1所示。
此外,注意有些平台上中断申请方式可能与驱动中默认实现方式不同,此时需修改ch9434.c文件中ch943x_spi_probe的相关代码
注:默认情况下请不要修改uart时钟,若确实需修改以支持部分非标波特率,可在ch943x_probe中修改:
freq = 32 *1000000 *15 / clkdiv;
2.2 静态编译驱动
(1)将驱动程序拷贝到内核目录:$kernel_src\\drivers\\tty\\serial
(2)向$kernel_src\\drivers\\tty\\serial\\Konfig 中添加:
config SERIAL_CH9434
tristate "SERIAL_CH9434 serial support"
depends on SPI
select SERIAL_CORE
help
This selects support for ch9434 serial ports.
(3)向$kernel_src\\drivers\\tty\\serial\\Makefile 中添加:
obj-$(CONFIG_SERIAL_CH943X)+= ch9434.o
(4)运行make menuconfig,选择驱动/tty/serial下的ch9434 serial support,然后保存配置。
(5)重新编译系统
2.3 动态编译驱动—方式1
(1)拷贝驱动文件至用于添加驱动的package/kernel目录下
(2)新建模块目录,如:ch9434,然后添加相关的Makefile和Kconfig文件,通常可以从系统已有的其他驱动下拷贝然后修改
(3)运行“make menuconfig”然后选中“ ch9434 serial support”作为“modules”项
(4)单独编译模块,命令为:
make package/kernel/ch9434/compile V=s
2.4 动态编译驱动—方式2
拷贝驱动文件至宿主机工作目录,在driver目录下新增Makefile文件,如下所示:
KERN_DIR = /home/Linux-5.4
all:
make -C $(KERN_DIR) M=`pwd` modules
$(CROSS_COMPILE)gcc -o ch9434 ch9434.c
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
rm -f ch9434
obj-m += ch9434.o
注意:此方式需系统下提前配置交叉编译工具链,在如上Makefile文件中修改KERN_DIR为已编译的内核目录。同时设置环境变量如下:
export ARCH=arm
export CROSS_COMPILE=arm-buildroot-linux-gnueabihf
export PATH=$PATH:/home/xxx/sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
在driver目录下直接执行make,成功时可生成ch9434.ko驱动模块。
3 加载驱动并验证
3.1 加载驱动
[root@100ask:/mnt/ch9434]# insmod ch9434.ko
[ 477.091787] ch9434: loading out-of-tree module taints kernel.
[ 477.096776] ch9434: module verification failed: signature and/or required key missing - tainting kernel
[ 477.109272] ch9434: SPI driver for spi to serial chip ch9434, etc.
[ 477.114026] ch9434: V1.00 On 2020.06.17
[ 477.123448] ch943x_spi spi0.1: change to SPI MODE 3!
3.2 查看串口节点
进入/dev目录,可以看到出现ttyWCH0、ttyWCH1、ttyWCH2和ttyWCH3设备节点,表示加载成功。
[root@100ask:/dev]# ls ttyWCH*
ttyWCH0 ttyWCH1 ttyWCH2 ttyWCH3
3.3 验证SPI通讯
ch943x_probe中会自动调用ch943x_scr_test接口,向4个串口的SPR寄存器分别写入0x55和0x66并读取寄存器值,若读取与写入的数值相匹配,则SPI接口通讯正常。
static int ch943x_scr_test(struct uart_port *port)
struct ch943x_port *s = dev_get_drvdata(port->dev);
dev_vdbg(&s->spi_dev->dev,"******Uart %d SPR Test Start******\\n", port->line);
ch943x_port_write(port, CH943X_SPR_REG,0x55);
ch943x_port_read(port, CH943X_SPR_REG);
ch943x_port_write(port, CH943X_SPR_REG,0x66);
ch943x_port_read(port, CH943X_SPR_REG);
dev_vdbg(&s->spi_dev->dev,"******Uart %d SPR Test End******\\n", port->line);
return 0;
使用前需在驱动程序中定义宏:
#define DEBUG
#define VERBOSE_DEBUG
以及修改printk内核打印等级:
[root@100ask:~]# echo 8 4 1 7 > /proc/sys/kernel/printk
加载驱动后查看内核打印信息:
[root@100ask:/mnt/ch9434]# insmod ch9434.ko
[ 477.091787] ch9434: loading out-of-tree module taints kernel.
[ 477.096776] ch9434: module verification failed: signature and/or required key missing - tainting kernel
[ 477.109272] ch9434: SPI driver for spi to serial chip ch9434, etc.
[ 477.114026] ch9434: V1.00 On 2020.06.17
[ 477.123448] ch943x_spi spi0.1: change to SPI MODE 3!
[ 477.129197] ch943x_spi spi0.1: ch943x_port_write - reg:0x81, val:0x 0
[ 477.135149] ch943x_spi spi0.1: ch943x_port_write - reg:0x84, val:0x 0
[ 477.141604] ch943x_spi spi0.1: ch943x_port_read - reg:0x 6, val:0x 0
[ 477.148458] ch943x_spi spi0.1: ******Uart 0 SPR Test Start******
[ 477.154347] ch943x_spi spi0.1: ch943x_port_write - reg:0x87, val:0x55
[ 477.160705] ch943x_spi spi0.1: ch943x_port_read - reg:0x 7, val:0x55
[ 477.166982] ch943x_spi spi0.1: ch943x_port_write - reg:0x87, val:0x66
[ 477.173556] ch943x_spi spi0.1: ch943x_port_read - reg:0x 7, val:0x66
[ 477.179305] ch943x_spi spi0.1: ******Uart 0 SPR Test End******
[ 477.185633] ch943x_spi spi0.1: ch943x_port_write - reg:0x91, val:0x 0
[ 477.192274] ch943x_spi spi0.1: ch943x_port_write - reg:0x94, val:0x 0
[ 477.198463] ch943x_spi spi0.1: ch943x_port_read - reg:0x16, val:0x 0
[ 477.209156] ch943x_spi spi0.1: ******Uart 1 SPR Test Start******
[ 477.214381] ch943x_spi spi0.1: ch943x_port_write - reg:0x97, val:0x55
[ 477.225183] ch943x_spi spi0.1: ch943x_port_read - reg:0x17, val:0x55
[ 477.232922] ch943x_spi spi0.1: ch943x_port_write - reg:0x97, val:0x66
[ 477.241444] ch943x_spi spi0.1: ch943x_port_read - reg:0x17, val:0x66
[ 477.246359] ch943x_spi spi0.1: ******Uart 1 SPR Test End******
[ 477.252862] ch943x_spi spi0.1: ch943x_port_write - reg:0xa1, val:0x 0
[ 477.259188] ch943x_spi spi0.1: ch943x_port_write - reg:0xa4, val:0x 0
[ 477.265396] ch943x_spi spi0.1: ch943x_port_read - reg:0x26, val:0x 0
[ 477.272512] ch943x_spi spi0.1: ******Uart 2 SPR Test Start******
[ 477.277949] ch943x_spi spi0.1: ch943x_port_write - reg:0xa7, val:0x55
[ 477.284520] ch943x_spi spi0.1: ch943x_port_read - reg:0x27, val:0x55
[ 477.290761] ch943x_spi spi0.1: ch943x_port_write - reg:0xa7, val:0x66
[ 477.297358] ch943x_spi spi0.1: ch943x_port_read - reg:0x27, val:0x66
[ 477.303202] ch943x_spi spi0.1: ******Uart 2 SPR Test End******
[ 477.309544] ch943x_spi spi0.1: ch943x_port_write - reg:0xb1, val:0x 0
[ 477.315969] ch943x_spi spi0.1: ch943x_port_write - reg:0xb4, val:0x 0
[ 477.322556] ch943x_spi spi0.1: ch943x_port_read - reg:0x36, val:0x 0
[ 477.329200] ch943x_spi spi0.1: ******Uart 3 SPR Test Start******
[ 477.334860] ch943x_spi spi0.1: ch943x_port_write - reg:0xb7, val:0x55
[ 477.341359] ch943x_spi spi0.1: ch943x_port_read - reg:0x37, val:0x55
[ 477.347567] ch943x_spi spi0.1: ch943x_port_write - reg:0xb7, val:0x66
[ 477.354204] ch943x_spi spi0.1: ch943x_port_read - reg:0x37, val:0x66
[ 477.360005] ch943x_spi spi0.1: ******Uart 3 SPR Test End******
[ 477.366257] ch943x_spi spi0.1: ch943x_port_write - reg:0xc8, val:0xcd
[ 477.372805] ch943x_spi spi0.1: ch943x_port_read - reg:0x48, val:0xcd
[ 477.382495] ch943x_spi spi0.1: ch943x_probe - devm_request_threaded_irq =84 result:0
[ 477.392463] cpu cpu0: Looking up cpu-supply from device tree
3.4 验证IO中断功能
驱动程序处理串口数据的发送,接收以及Modem输入中断事件均是在中断服务函数中进行,因此当SPI接口正常串口功能不正常,需检查中断功能是否正常,当执行串口发送时,驱动会自动打开串口发送中断(IETHRE),芯片的INT引脚会输出低电平请求CPU中断。在打开调试开关时,正常情况下可观察到中断服务函数运行的打印信息。此外,也可以手动给CPU的IO口拉高/拉低,测试中断是否能正常应。
4 功能测试
编译demo目录下tty_test_ch9434.c得到可执行目标程序app,运行演示:
./app -D /dev/ttyWCH0 -S 115200 -v
//参数含义
-D --device tty device to use
-S --speed uart speed
-v --verbose verbose (show rx buffer)
-f --hardflow open hardware flowcontrol
-R --rs485 enable rs485 function
-s --savefile save rx data to file
4.1 串口收发
(1)串口发送数据流程为:应用软件调用write方法—>驱动接收请求并将数据拷贝至串口circ_buf,打开串口发送空中断(IER寄存器IETHRE位)->执行中断服务函数->判断为发送空中断时执行ch943x_handle_tx函数,从circ_buf中拷贝数据,通过SPI发送函数,将数据写入到串口发送FIFO寄存器->发送完成再次触发空中断,当circ_buf仍有数据则继续发送,否则关闭发送空中断。
(2)串口接收数据流程为:芯片RXD引脚收到串口数据后->执行中断服务函数->判断IIR中断类型为接收数据超时或接收数据可用时执行ch943x_handle_rx函数->读取FIFO长度,通过SPI读取函数,从串口接收FIFO寄存器读取数据并拷贝至串口circ_buf->退出中断->通过应用层有数据可读,应用软件调用read方法读数据。
串口收发流程图:
通过串口向PC收发数据测试:
串口发送0x00~0xFF/接收0x61~0x64
4.2 使用MODEM功能
引脚介绍:
MODEM输出测试方法: 程序中设置MODEM信号输出后,可以直接用万用表测试信号电压,也可以将9434评估板串口的输出引脚连接USB转串口模块(如CH342)的MODEM输入引脚,CH342的USB端连接PC;打开串口调试工具,通断发送端连接,接收端可观察数据变化。
MODEM输入测试方法:
进入开发板系统,由PC端串口输出,调试工具中开启DTR和RTS,CH9434串口输入:
接收端运行应用程序,输入“g”获取modem状态:
[root@100ask:/mnt/ch9434/demo]# ./app -D /dev/ttyWCH0 -S 115200 -v
press s to set modem, z to clear modem, g to get modem,b to send break, w to write, r to read, q for quit.
g
DSR Active!
CTS Active!
press s to set modem, z to clear modem, g to get modem,b to send break, w to write, r to read, q for quit.
4.3 硬件流控
串口流控功能使能是将 MCR寄存器的AFE位置1,CH9434 将自动进行硬件流控。芯片将自动根据 FIFO 大小对流控引脚进行操作。启用自动流控后,CTS 有效时芯片串口将连续发送数据,CTS 引脚无效时,串口最多发送8 字节数据后停止发送。RTS 在触发 FIFO 达到设定的流控字节数目后自动失效。
FCR 寄存器的 RECVTG1 和 RECVTG0 位用于设置接收 FIFO 的中断和硬件流控制的触发点,00 对应256 个字节,即接收满256 个字节产生接收数据可用的中断,并在使能硬件流控制时自动无效 RTS 引脚,01 对应512 个字节,10 对应1024 个字节,11 对应1285 个字节。
PC发送端串口工具设置开启流控制:
接收端运行应用程序:
4.4 GPIO测试
CH9434 支持部分引脚复用为 GPIO 功能,最多支持25 路,每个 IO 都可以独立设置方向、上拉电阻和下拉电阻配置。启用 GPIO 功能后,将自动失效该 IO 其他复用功能。GPIO 功能在设置时需要注意该 IO 原来功能的模式,设置时需要注意 DIR、PD、PU 等 IO 寄存器的顺序防止 IO 出现“抖动”。
GPIO输出测试:
测试方法:以GPIO0为例,该IO默认复用为CTS0;将该IO配置输出高/低电平,此时默认功能将失效。 添加代码:
/* gpio test */
ret = libtty_gpioenable(fd, 0, 1);
if (ret != 0)
printf("libtty_gpioenable error.\\n");
exit(0);
ret = libtty_gpiopullup(fd, 0, 1);
if (ret != 0)
printf("libtty_gpiopullup error.\\n");
exit(0);
ret = libtty_gpiodir(fd, 0, 1);
if (ret != 0)
printf("libtty_gpiodir error.\\n");
exit(0);
ret = libtty_gpioset(fd, 0, 1);
if (ret != 0)
printf("libtty_gpioset error.\\n");
exit(0);
使用万用表查看GPIO0输出电平 输出低电平:
输出高电平:
GPIO输入测试:
测试方法:以GPIO11为例,配置为输入模式,gpioval表示IO值,1个字节表示8个IO,将对应IO交替接地和3.3V引脚,运行应用程序查看输入值。
测试代码:
ret = libtty_gpioenable(fd, 1, 1);
if (ret != 0)
exit(0);
ret = libtty_gpiopullup(fd, 1, 0);
if (ret != 0)
exit(0);
ret = libtty_gpiodir(fd, 1, 0);
if (ret != 0)
exit(0);
ret = libtty_gpioget(fd, 1, &gpioval);
if (ret != 0)
exit(0);
else
printf("gpioval = 0x%02x \\n", gpioval);
GPIO11即GPIO1_4,输入高电平时,gpioval应等于11111111B;输入低电平时,gpioval应等于11110111B 。
测试结果:
GPIO11接地:gpioval = 0xf7
GPIO11接3.3V:gpioval = 0xff
4.5 RS485串口测试
CH9434 串口提供 RS485 切换引脚 TNOW,引脚功能与其他功能复用,当启用 TNOW 功能后,将自动失效原 MODEM 信号功能。TNOW 还支持极性调节,以适应不同的极性使用场景。
添加代码:
char rs485 = 1;
ret = libtty_rs485set(fd, rs485);
if (ret != 0)
printf("libtty_rs485set %s error.\\n", rs485 ? "enable": "disable");
exit(0);
测试方法: 连接CH9434评估板P2和P4(参照原理图),使用RS485传输;连接串口0和串口1对应的RS485引脚(P9和P15),串口0发送0x00~0x0FF,串口1接收显示:
基于龙芯 2K1000 的嵌入式 Linux 系统移植和驱动程序设计
第 3 章 嵌入式软件系统移植 本课题中嵌入式系统正常工作的前提是嵌入式软件系统完整且能正常工作, 以便为之后的软件开发提供一个能够正常工作的平台。引导程序 PMON 需要完成 内核引导,嵌入式 Linux 内核需要具有完备的功能且能够正常使用,根文件系统要 完成启动过程中初始化工作。 3.1 PMON 启动流程与编译 3.1.1 PMON 目录结构及主要命令 PMON 目录结构如表 3-1 所示, PMON 目录下包含处理器相关代码和一些基 本的设备驱动, Targets 目录下有针对不同板卡详细的配置文件 [39] 。 PMON 主要命令包括常用指令和对设备的操作指令,例如设置网络设备 IP 的 命令 ifaddr ,网络连接命令 ping 和查看设备命令 devls 等。 3.1.2 PMON 启动流程分析 龙芯 2K1000 处理器通过 SPI 总线接口连接 NOR Flash , PMON 镜像文件存储 在 NOR Flash 中, NOR Flash 的物理地址起始地址为 0x1fc00000 ,该地址为处理器 的 SPI 总线控制器。但是程序主要在内存中运行,因此需要的改地址映射的虚拟地 址起始地址为 0xbfc00000 。处理器上电后,直接从 0xbfc00000 开始运行 PMON 的 代码。 PMON 有两部分代码, PMON 镜像文件开头部分为第一部分汇编代码,这部 分代码上电后直接运行,因此没有压缩,执行完毕会执行第二部分经过压缩的 C 代 码。 PMON 分为两部分代码的原因在于系统初始阶段并没有准备好 C 语言运行的 环境,因此需要汇编代码来完成一些处理器和内存等设备的初始化,完成准备工作 [40] 。 PMON 启动流程如图 3-1 所示,准备工作完成后, start.s 将第二部分压缩的 C 代码解压,之后 C 代码就在内存中运行。 start.s 是 PMON 镜像文件的开头,因此 这部分代码存放在虚拟地址 0xbfc00000 ,这段代码初始化寄存器、内存、串口、网 口之后,将 PMON 代码搬运到内存中运行,之后开始执行 initmips 函数。 initmips 函数在 Targets\\LS2K\\ls2k\\tgt_machdep.c 文件中,该函数首先执行 tgt_cpufreq 函数 来探测 CPU 频率,之后执行 dbginit 函数对命令、文件系统、可执行文件和环境变 量进行初始化,初始化 PCI 总线和设备,加载串口、网络接口、视频接口和 USB 接口等设备的驱动,构建一个可以进行人机交互的命令行。 3.1.3 PMON 编译 1 )下载 PMON 源代码,并解压。 2 )获取编译 PMON 的 gcc 编译器 3 )安装编译 PMON 必要的依赖工具 #sudo apt-get install xutils-dev #sudo apt-get install bison flex build-essential patch #cd /home/troy/pmon-loongson3-20200728/tools/pmoncfg #make pmoncfg #cp pmoncfg /usr/bin 4 )在 PMON 源码存放目录下,更改相关文件配置编译所需环境变量 #vi .bashrc 在文件末尾增加三行 pmon 交叉编译工具链和编译器的路径信息 export LD_LIBRARY_PATH=/home/troy/pmongcc/opt/gcc-4.4-gnu/lib: exportCROSS_COMPILE=/home/troy/pmongcc/opt/gcc-4.4-gnu/bin/mipsel-linux export PATH=/home/troy/pmongcc/opt/gcc-4.4-gnu/bin/:$PATH #source .bashrc 使设置的环境变量生效 5 )进入 pmon 源码目录进行编译 #cd /home/troy/pmon-loongson3-20200728/zloader.ls2k #make cfg #make all tgt=rom #make dtb 如图 3-2 所示编译完成后在 pmon 源码目录下的 zloader.ls2k/ 目录下生成 gzrom.bin 和 gzrom-dtb.bin 。 如果更改了 Targets/LS2K/conf/ls2k 目录下的文件源代码或者参数 , 则在编译 前要执行 make cfg ,使得更改生效,如果普通编译没有更改配置,则每次无需都执 行 make cfg 命令。执行 make dtb 可以将设备树 dtb 和 gzrom.bin 结合生成 gzrom dtb.bin ,此命令可以在上面编译完成后执行。3.2 嵌入式 Linux 内核移植
3.2.1 Linux 内核简介 本课题中应用程序、 Linux 内核、驱动程序、硬件关系如图 3-3 所示, Linux 内 核是应用程序和硬件设备之间的媒介,内核将应用程序的请求和命令通过底层程 序传递给硬件设备实现对硬件的操作。 Linux 内核根据功能分为五个内核子系统, 分别为进程调度、内存管理、文件系统、进程通信和网络。进程调度是内核的核心 功能,多个进程需要使用 CPU 有限的资源,但是 CPU 一次只能处理一个进程,进 程调度会通过合理切换多进程让宏观上多进程并行,无论何时都有进程运行,使 CPU 资源得到最有效利用。内存管理使用一块内存区域给多个进程使用,节省内 存资源。虚拟文件系统屏蔽了不同文件的细节,让用户可以使用一种方式通过例如 read 和 write 等统一接口实现对不同类型文件的访问,如果没有虚拟文件系统,用 户访问文件只能直接访问存储设备上文件存放的位置,这显然对于用户访问文件 非常不方便。进程通信是指内核支持多进程之间通过信号量、共享内存等方式,实 现互斥利用资源以及进程间消息传递,随着软件功能越来越复杂,目前几乎没有单 进程的软件,因此进程调度属于内核中非常重要的功能。网络子系统包含各种网络 协议以及对网络设备的驱动程序,可以让系统实现网络传输功能 [41] 。 3.2.2 Linux 内核的配置与编译 对于龙芯 2K1000 处理器,考虑到软件的可互换性和可移植性,本课题选择龙 芯官方获得支持 MIPS 架构的嵌入式 Linux 源代码,在 ubuntu 虚拟机中对 Linux 内 核进行裁剪和交叉编译。主要工作流程如下: 1 )获取 Linux 源码 从龙芯官方 ftp 下载内核源码压缩包并解压,生成对应的内核源码目录。 2 )配置环境变量 #vi .bashrc 在文件最后一行增加交叉编译工具链的绝对路径 #export PATH=/home/troy/opt/gcc-4.9.3-64-gnu/bin:$PATH #source .bashrc 使配置的环境变量生效 3 )内核裁剪配置 Linux 内核代码中提供使用图形化界面进行内核裁剪的工具,本课题不直接修 改 Linux 的编译文件代码,而是使用图形界面工具进行内核裁剪,命令如下: #make ARCH=mips CROSS_COMPILE=mips64el-linux- menuconfig 运行该命令之后会弹出如图 3-4 所示的内核配置界面。 由于本课题使用龙芯官方维护 Linux 内核,需要根据龙芯 2K1000 处理器实际 情况对内核进行一些裁剪: ( 1 )增加帧缓冲区驱动 Device Driver — > Graphics support — > Support for frame buffer devices — > Loongson Frame Buffer Support (2)增加龙芯 2K1000 处理器 SPI 总线控制驱动 Device Driver — > SPI support — > <*>Loongson SPI Controller Support (3)增加龙芯 2K1000 处理器 VGA 驱动 Device Driver — > Graphics support — > <*>Loongson VGA DRM [ ] use platform device (4)将自己开发的网络驱动等编译进内核 (5)删除如邮箱、无线网络等不需要使用的驱动程序和功能 4 )编译内核 #make ARCH=mips CROSS_COMPILE=mips64el-linux- ,对内核进行编译。如 图 3-5 所示编译完毕之后在内核目录下生成 vmlinux 为可移植的 Linux 内核镜像, vmlinuz 为可移植的 Linux 内核压缩镜像。由于嵌入式系统一般资源有限,所以使 用 vmlinuz 作为系统内核镜像。3.3 根文件系统制作 3.3.1 Linux 根文件系统 内核启动后首先挂载根文件系统,根文件系统除了有文件系统存储和管理数 据的功能,也有普通文件系统没有的功能。根文件系统中一般在 /etc 目录下存放着 许多初始化脚本和配置文件,负责系统启动过程中的初始化功能。根文件系统在内 核启动最后阶段被挂载到根目录 / ,其他目录再挂载到根目录 [42] 。 虽然根文件系统负责 Linux 内核启动过程中的初始化工作,但在嵌入式系统 中它与内核一般是分开的,这是由于内核负责一些进程调度等操作系统的基本工 作,这些基本工作在所有处理器平台下基本相同。但是根文件系统负责配置工作, 不同的处理器配置方法和具体内容不同,因此根文件系统和内核分离,可以让嵌入 式软件系统的可移植性更好。 3.3.2 根文件系统制作 制作根文件系统常用工具是 BusyBox 和 Buildroot [43] ,由于 BusyBox 使用较为 繁琐,因此本课题使用 Buildroot 工具来制作根文件系统。 Buildroot 包含了 Makefile 和 Kconfig ,可以用来构建内核、引导程序和根文件系统,在嵌入式开发中主要用 来构建根文件系统。使用 Buildroot 制作根文件系统镜像步骤如下: 1 )下载并配置 Buildroot 下载并解压 Buildroot 之后,使用龙芯 2k1000 对应的 config 文件替换之前默 认 config 文件,具体命令如下: #wget http://ftp.loongnix.org/embedd/ls2h/Buildroot/ #sudo tar -zxvf Buildroot.tar.gz #cp ls2k_docker-systemd-gcc-4.9.3.config .config 2 )创建自动编译脚本 通过使用可执行脚本,将编译根文件系统步骤放在一个脚本文件中,减少操作 复杂度,具体命令如下: #touch cmd.sh #vi cmd.sh 脚本内容如下: #! /bin/bash export LANG=C export PATH=/home/troy/opt/gcc-4.9.3-64-gnu/bin/:$PATH make ARCH=mips CROSS_COMPILE=mips64el-linux- -j2 #chmod 777 cmd.sh 3 )使用图形化界面对 Buildroot 进行配置 #make menuconfig Buildroot 图形化配置界面如图 3-6 所示,具体配置步骤如下: ( 1 ) Target options — > 根据龙芯 2K1000 处理器实际参数配置 CPU 参数为小端 MIPS64 (2) Toolchain — > 设置工具链 gcc-4.9.3-64-gun 的路径,根据虚拟机中工具链实际的目录来填写 (3) System configuration — > 包含了开机之后系统的欢迎语和用户名及其密码 (4) Run a getty (login prompt) after boot — > 配置串口的波特率,由于本课题中不使用串口而是直接外接屏幕来显示,因此 该项可以不进行设置。 (5) Kernel — > 由于制作不附带内核的根文件系统,该项为空 (6) Target packages — > 根据实际需求选择附带的嵌入式软件,本课题中只需要构建一个最基本的根 文件系统,因此不需要进行选择。 4 )开始编译 buildroot 在 buildroot 的顶层目录下执行如下命令: #./cmd.sh 执行自动编译脚本进行编译。 编译成功后,如图 3-7 所示 /buildroot/output/images/ 目录下会生成 cpio 、 cpio.gz 、 ubi 、 ubifs 以及 yaffs2 五种类型的根文件系统镜像。由于系统使用 SSD 卡作为存储 介质,因此选择除 ubifs 之外格式的文件系统。
以上是关于CH9434 嵌入式Linux与安卓系统驱动移植和使用教程的主要内容,如果未能解决你的问题,请参考以下文章
Android安卓书籍推荐《Android驱动开发与移植实战详解》下载
基于龙芯 2K1000 的嵌入式 Linux 系统移植和驱动程序设计
嵌入式Linux第二部分 - 裸机开发/系统移植/驱动开发/内核开发