嵌入式的入门路程

我的第一篇博客

第一次写博客,记录我学习Linux嵌入式的过程

主要往Linux嵌入式软件应用方向学习。
在这里插入图片描述

学习主要用到的工具:

  1. VMware 15.5.0
  2. Ubuntu 18.0.4
  3. MobaXterm_Personal_12.2
  4. FileZilla Client
  5. Source Insight 4.0
  6. notepad++
  7. NXP I.MX6ULL 开发板
  8. QT4.8

安装搭建开发环境

学习路线

1. C语言基础
2. Linux基本知识
Linux文件目录与权限
Linux shell 与常用命令
3、Linux C编程编译
熟悉掌握GCC编译器的编译流程:预处理、汇编、编译和链接Makefile的基础以及基础语法和使用
4、ARM汇编基础
熟悉常用汇编指令以及了解寄存器的运行
5、构建系统
U-Boot的编译、使用方法、启动流程以及如何移植
Linux Kernel 的编译、移植。
zImage内核文件、设备树文件更新到开发板上
根文件系统:这里部分暂时不是很懂
6、系统和程序的烧写
使用开发板官方的烧写工具
7、Linux应用开发基础
文件IO;进程与线程的理解;

8、Linux驱动的基础
查看芯片手册(对芯片的使用理解更深入);
掌握基本的电路原理图(能基本看懂和使用就行);
驱动程序的框架、设计思想(分层/分离/总线设备驱动)
设备树的引入与改造
了解GPIO和Pinctrl子系统的基本原理和使用
Linux异常与中断的概念以及处理流程
9、ARM裸机的操作与使用
中断实验;LCD显示;
I2C协议的编程;SPI编程(目前还未深入掌握)
主要关注传感器模块的使用(注重使用,不必纠结原理)
10、QT的开发以及移植到开发板上
实现通过GUI达到人机交互的功能(还未学习QT移植的具体操作与方法)

第一个Linux App,实现简单的文本读写

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    //用open去创建一个文件
    int fd=open("./2.txt", O_RDWR|O_CREAT|O_TRUNC,0777);
    if(fd==-1)
    {
        printf("-1文件创建失败");
        return -1;
    }
    else {
        printf("创建成功\n\r");
    }
    //定义写入Buf数组
    char writBuf[100]="my ID is  315\n\r my  name is  wss";
    //对文件进行数据写入
    int writNum=write(fd,writBuf,strlen(writBuf));

  printf("writenum:写入成功%d\n\r",writNum);
   //将光标从末尾移到开头
    int lseekNum=lseek(fd,0,SEEK_SET);
    //定义读取Buf数组并进型数据初始化
    char readBuf[100] = {};
    //对文件进行数据读取
    int num=read(fd,readBuf,100);
    printf("readBuf:%s\n\r",readBuf);
    printf("num:%d\n\r",num);
    close(fd);
    return 0;
}
 

第一个驱动程序

韦东山老师的程序

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>

/* 1. 确定主设备号                                                                 */
static int major = 0;
static char kernel_buf[1024];
static struct class *hello_class;

#define MIN(a, b) (a < b ? a : b)

/* 3. 实现对应的open/read/write等函数,填入file_operations结构体                   */
static ssize_t hello_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	int err;
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	err = copy_to_user(buf, kernel_buf, MIN(1024, size));
	return MIN(1024, size);
}

static ssize_t hello_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
	int err;
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	err = copy_from_user(kernel_buf, buf, MIN(1024, size));
	return MIN(1024, size);
}

static int hello_drv_open (struct inode *node, struct file *file)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}

static int hello_drv_close (struct inode *node, struct file *file)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}

/* 2. 定义自己的file_operations结构体                                              */
static struct file_operations hello_drv = {
	.owner	 = THIS_MODULE,
	.open    = hello_drv_open,
	.read    = hello_drv_read,
	.write   = hello_drv_write,
	.release = hello_drv_close,
};

/* 4. 把file_operations结构体告诉内核:注册驱动程序                                */
/* 5. 谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数 */
static int __init hello_init(void)
{
	int err;
	
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	major = register_chrdev(0, "hello", &hello_drv);  /* /dev/hello */


	hello_class = class_create(THIS_MODULE, "hello_class");
	err = PTR_ERR(hello_class);
	if (IS_ERR(hello_class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		unregister_chrdev(major, "hello");
		return -1;
	}
	
	device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello"); /* /dev/hello */
	
	return 0;
}

/* 6. 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数           */
static void __exit hello_exit(void)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	device_destroy(hello_class, MKDEV(major, 0));
	class_destroy(hello_class);
	unregister_chrdev(major, "hello");
}


/* 7. 其他完善:提供设备信息,自动创建设备节点                                     */

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

使用Source Insight 进行代码的编写,事先导入对应的Linux源码文件,方便查看内核源码
先分析的是入口函数:
register_chrdev函数注册字符设备驱动
第一个参数是主设备号,0代表由系统动态分配。
第二个参数是设备的名字
第三个参数是文件操作指针,file_operations结构体。
class_create动态创建设备的逻辑类,并完成部分字段的初始化,然后将其添加到Linux内核中
device_create函数,创建一个设备节点,并注册它到sysfs中
file_operations结构体。
对应的各个函数open,read,write,close;
read使用copy_to_user,从内核空间到用户空间
write使用copy_from_user,从用户空间到内核空间

第一篇完结,2020/6/8 10:00

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值