自学内容网 自学内容网

系统移植&驱动开发试题

系统移植

1.Makefile/.config/Kconfig的区别

  • Kconfig:定义配置项
  • Makefile:说明配置项的编译方法
  • .config:控制配置项编译进内核、编译成模块还是不编译

2.make menuconfig/make <board_name>_defconfig/make all的关系

  • make <board_name>_defconfig:默认板子缺省配置文件
  • make menuconfig:基于图形化界面信息配置 
  • make all:根据.config文件,决定哪些文件被编译到uboot镜像文件中,哪些文件不被编译到镜像文件中

3.开发板如何部署Linux操作系统的,写出bootcmd和bootargs的参数设置

  • 1.设置好开发板的IP以及虚拟机的IP,让开发板可以ping通ubuntu
  • 2.通过tftp服务将设备树的镜像和内核镜像下载到开发板内存
  • 3.设置bootargs,当u-boot引|导内核启动后按照bootargs的设置给操作系统远程挂载一个文件系统

bootcmd环境变量的设置方式:

  • 方式1: setenv bootcmd u-boot命令1\;u-boot命令2\;...
  • 方式2: setenv bootcmd "u-boot命令1;u-boot命令2;..."
setenv bootcmd "tftp 0xc2000000 uImage; \
                tftp 0xc4000000 \
                stm32mp157a-fsmp1a.dtb;\
                bootm 0xc2000000 - 0xc4000000"
setenv bootargs root=/dev/nfs nfsroot=192.168.1.250:\
                /home/ubuntu/nfs/rootfs,tcp,v4 rw \
                console=ttySTM0,115200 init=/linuxrc \
                ip=192.168.1.10

4.uboot环境变量中mmc read,mmc write命令如何使用

        mmc read addr blk# cnt

        addr: 表示保存从mmc读出数据的内存地址

        blk#: 表示要读取的mmc的sector地址

        cnt: 表示要读取多少个sector的数据

        mmc write addr blk# cnt

        addr: 表示要写入mmc设备的原始数据的内存地址

        blk#: 表示要写入的mmc的sector地址

        cnt: 表示要写取多少个sector的数据

5.配置内核和编译内核镜像的命令

        配置内核:make menuconfig

        编译内核镜像:make uImage LOADADDR=0xC2000000 单独编译linux内核

                                make uImage dtbs LOADADDR=0xC2000000 编译内核和设备树

6.第一次配置内核时,应使用的缺省内核配置文件是什么

        make <board_name>_defconfig生成.config文件

7.如何添加自己的 LED 灯驱动程序,采用模块化方式编译,并且进行测试

   备注:需要写出 makefile/.config/kconfig 这三个文件添加哪些内容

8.如何制作ramdisk.img 镜像文件

  • 1.进入到nfs目录下
  • 2.使用dd命令制作一个64M大小的文件
  • 3.使用mkfs.ext4对ramdisk进行格式化,格式化为ext4格式
  • 4.将ramdisk 挂载到/mnt目录
  • 5. 使用strip命令压缩文件的体积
  • 6.将~/nfs/rootfs中的内容拷贝到/mnt目录下
  • 7.解除挂载
  • 8.使用gzip对ramdisk进行压缩
  • 9.使用mkimage命令给ramdisk.gz文件添加64字节的文件头得到ramdisk.img镜像文件
  • 10.拷贝ramdisk.img到~/tftpboot目录下
  • 11.设置内核通过ram挂载根文件系统的大小
  • 12.对ramdisk.img的镜像文件进行测试

9.请写出如何将uboot镜像文件烧写到EMMC设备中

  • 1. tf卡通过读卡器被ubuntu识别
  • 2. 使用ls /dev/sd*命令查看tf卡是否被ubuntu识别成功
  • 3. 拷贝sdtools.sh脚本文件到u-boot源码目录下
  • 4. 执行脚本文件,将镜像文件烧录到tf卡中

驱动开发

1.请描述printk和printf使用的区别

  • printk允许通过指定一个标志来设置优先级,从而决定这条打印是否需要打印出来
  • printk函数运行环境在内核态,printf函数在用户态
  • printf是不能设置优先级的,printk函数可以设置优先级
  • 当优先级确定时,printk可以通过修改控制台输出的优先级来决定是否输出某条打印
  • 不指定优先级时,printk会有一个默认的优先级

2.编写一个设备树节点,要求编写出五种不同键值对内容

mynode@0x12345678{
    compatible = "hqyj,mynode";
    astring="hello 24051";
    uint  =<0xaabbccdd 0x11223344>;
    binarry=[00 0c 29 7b f9 be];
    mixed ="hello",[11 22],<0x12345678>;
};

 3. 编写对linux内核模块编译的Makefile 文件,需要写完整

arch ?= arm
modname ?= demo

ifeq ($(arch),arm)
KERNELDIR:=/home/ubuntu/linux-5.10.61
else
KERNELDIR := /lib/modules/$(shell uname -r)/build 
endif

PWD:= $(shell pwd)

all:
make -C $(KERNELDIR) M=$(PWD) modules

clean:
make -C $(KERNELDIR) M=$(PWD) clean   

obj-m := $(modname).o 

4.编程实现使用iic子系统,采集温湿度传感器值,请大家按照以下需求编写
        需要1:头文件(5分)
        需要2:驱动代码(10分)
        需求 3:应用层代码(5分)
        读取温度寄存器地址为:0xE3
        读取湿度寄存器地址为:0xE5

head.h

#ifndef __HEAD_H__
#define __HEAD_H__ 

//功能码构建例子不传递第三个参数:
#define  GET_HUM _IOR('m',1,int)
#define  GET_TEM _IOR('m',0,int)
 
#endif

iic.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include "head.h"
int major;
char kbuf[128] = {0};
struct class *cls;
struct device *dev;
struct i2c_client *client1;
// 封装一个读取温湿度数据的函数
// reg:寄存器地址
short si7006_read_hum_tem(char reg)
{
    int ret;
    char r_buf = reg;
    short value; // 保存从机发送的数据
    // 消息封装
    struct i2c_msg r_msg[] = {
        [0] = {
            .addr = client1->addr,
            .flags = 0,
            .len = 1,
            .buf = &r_buf,
        },
        [1] = {
            .addr = client1->addr,
            .flags = 1,
            .len = 2,
            .buf = (u8 *)&value,
        },

    };
    //进行消息传输
    ret = i2c_transfer(client1->adapter, r_msg, 2);
    if (ret != 2)
    {
        printk("消息传输失败\n");
        return ret;
    }
    //将获取到的消息返回
    return value;
}
// 封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}
ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
{
    unsigned long ret;
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);

    // 向用户空间读取拷贝
    if (size > sizeof(kbuf)) // 用户空间期待读取的大小内核满足不了,那就给内核支持的最大大小
        size = sizeof(kbuf);
    ret = copy_to_user(ubuf, kbuf, size);
    if (ret) // 拷贝失败
    {
        printk("copy_to_user filed\n");
        return ret;
    }
    return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{
    unsigned long ret;
    // 从用户空间读取数据
    if (size > sizeof(kbuf)) // 用户空间期待读取的大小内核满足不了,那就给内核支持的最大大小
        size = sizeof(kbuf);
    ret = copy_from_user(kbuf, ubuf, size);
    if (ret) // 拷贝失败
    {
        printk("copy_to_user filed\n");
        return ret;
    }

    return 0;
}

long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long argp)
{
    int tem, hum, ret; // 保存读取到的温湿度数据
    switch (cmd)
    {
    case GET_HUM:
        hum = si7006_read_hum_tem(0XE5);
        ret = copy_to_user((unsigned int *)argp, &hum, 4); // 将读取到的温湿度数据传递到应用程序
        if (ret)                                           // 拷贝失败
        {
            printk("copy_to_user filed\n");
            return ret;
        }
        break;
    case GET_TEM:
        tem = si7006_read_hum_tem(0XE3);
        ret = copy_to_user((unsigned int *)argp, &tem, 4);
        if (ret) // 拷贝失败
        {
            printk("copy_to_user filed\n");
            return ret;
        }
        break;
    }

    return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}

// 定义操作方法结构体变量并赋值
struct file_operations fops = {

    .open = mycdev_open,
    .read = mycdev_read,
    .write = mycdev_write,
    .unlocked_ioctl = mycdev_ioctl,
    .release = mycdev_close,
};
// 给对象分配空间并且初始化
int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    client1 = client;
    // 字符设备驱动注册
    major = register_chrdev(0, "mychrdev", &fops);
    if (major < 0)
    {
        printk("字符设备驱动注册失败\n");
        return major;
    }
    printk("字符设备驱动注册成功:major=%d\n", major);
    // 向上提交设备类
    cls = class_create(THIS_MODULE, "si7006");
    if (IS_ERR(cls))
    {
        printk("向上提交设备类失败\n");
        return PTR_ERR(cls);
    }
    printk("向上提交设备类成功\n");
    dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "si7006");
    if (IS_ERR(dev))
    {
        printk("向上提交设备信息失败\n");
        return PTR_ERR(dev);
    }
    printk("向上提交设备信息成功\n");
    return 0;
}
int i2c_remove(struct i2c_client *client)
{
    // 设备信息的注销
    device_destroy(cls, MKDEV(major, 0));
    // 销毁设备类
    class_destroy(cls);
    // 注销字符设备驱动
    unregister_chrdev(major, "mychrdev");
    return 0;
}
// 定义设备树匹配的表
struct of_device_id oftable[] = {
    {
        .compatible = "hqyj,si7006",
    },
    {},
};

struct i2c_driver i2c_drv = {
    .probe = i2c_probe,
    .remove = i2c_remove,
    .driver = {
        .name = "si7006",
        .of_match_table = oftable,
    },
};
module_i2c_driver(i2c_drv);
MODULE_LICENSE("GPL");

test.c

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include<arpa/inet.h>
#include "head.h"

int main(int argc, char const *argv[])
{
    int tem, hum;
    float tem1,hum1;
    int fd = open("/dev/si7006", O_RDWR);
    if (fd < 0)
    {
        printf("打开设备文件失败\n");
        exit(-1);
    }
    while(1)
    {
        ioctl(fd,GET_HUM,&hum);//获取湿度
        ioctl(fd,GET_TEM,&tem);//获取湿度
        //进行数据的字节序转换
        hum=ntohs(hum);
        tem=ntohs(tem);
        //计算湿度
        hum1=(float)125*hum/65536-6;
        //计算温度
        tem1=175.72*tem/65536-46.85;
        printf("温度tem=%.3f\t湿度hum=%.3f\n",tem1,hum1);
        sleep(1);
    }
    close(fd);

    return 0;
}


原文地址:https://blog.csdn.net/2301_80922669/article/details/142823692

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!