嵌入式Linux驱动开发核心技巧(设备树+内核模块深度融合解析)

第一章:嵌入式Linux驱动开发概述

嵌入式Linux驱动开发是连接硬件与操作系统的核心环节,负责管理外设资源、提供统一接口供上层应用调用。在嵌入式系统中,由于硬件平台多样性和资源受限的特性,驱动程序往往需要高度定制化,以适配特定的SoC架构和外围设备。

驱动的基本分类

Linux设备驱动主要分为三类:
  • 字符设备:按字节流方式访问,如串口、按键等
  • 块设备:以数据块为单位进行读写,如SD卡、NAND Flash
  • 网络设备:负责数据包的收发,如以太网控制器

内核模块与驱动加载

大多数嵌入式驱动以可加载内核模块(LKM)形式存在,便于调试和维护。通过编写简单的模块代码可实现动态注册与卸载:

#include <linux/module.h>
#include <linux/kernel.h>

static int __init hello_init(void)
{
    printk(KERN_INFO "Hello, embedded Linux driver!\n");
    return 0; // 成功加载
}

static void __exit hello_exit(void)
{
    printk(KERN_INFO "Goodbye, driver world!\n");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
上述代码定义了一个最基础的内核模块,使用printk输出信息至内核日志,可通过insmod hello.ko加载,rmmod hello卸载。

开发环境关键组件

典型的嵌入式Linux驱动开发依赖以下工具链:
组件作用
Cross Compiler用于在x86主机上编译ARM/MIPS等目标平台代码
Kernel Headers提供编译模块所需的内核API声明
Device Tree描述硬件资源配置,解耦驱动与具体板级信息
graph TD A[硬件设备] --> B(Device Tree) B --> C[Linux内核] C --> D[设备驱动] D --> E[系统调用接口] E --> F[用户空间应用]

第二章:设备树原理与实践应用

2.1 设备树基本语法与DTS结构解析

设备树源文件(DTS)采用特定的语法描述硬件拓扑结构,是内核启动时解析硬件信息的基础。一个典型的DTS文件由节点和属性构成,节点代表硬件设备或子系统,属性则以键值对形式描述其特性。
DTS基本结构
每个DTS文件包含一个根节点,其下可嵌套多个子节点。节点名称遵循“设备@地址”格式,例如:

/ {
    model = "My Embedded Board";
    compatible = "myboard";

    soc {
        #address-cells = <1>;
        #size-cells = <1>;

        uart0: serial@10000000 {
            compatible = "snps,dw-apb-uart";
            reg = <0x10000000 0x1000>;
            interrupts = <32>;
        };
    };
};
上述代码定义了一个串口控制器节点。其中,reg 属性表示寄存器地址与长度,interrupts 指定中断号,compatible 用于匹配驱动。
常用属性说明
  • #address-cells:定义子节点地址字段的宽度(单元数)
  • #size-cells:定义大小字段的宽度
  • phandle:唯一标识节点的引用句柄

2.2 如何为自定义硬件编写设备树节点

在嵌入式Linux系统中,设备树(Device Tree)用于描述硬件拓扑结构。为自定义硬件添加节点时,需在.dtsi或.dts文件中定义兼容性、寄存器地址、中断等属性。
基本节点结构
一个典型的设备树节点包含唯一标签、兼容性字符串和资源定义:

my_device: my_device@10000000 {
    compatible = "vendor,my-device";
    reg = <0x10000000 0x1000>;
    interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&clk_periph>;
};
其中,compatible用于匹配驱动程序;reg指定寄存器基地址与长度;interrupts定义中断号与触发类型。
关键属性说明
  • compatible:格式为“制造商,设备型号”,驱动通过此字段绑定设备;
  • reg:物理地址与大小,需与硬件手册一致;
  • #address-cells 和 #size-cells:定义子节点的地址与大小字段宽度。

2.3 设备树与驱动匹配机制深入剖析

在现代Linux内核中,设备树(Device Tree)承担着描述硬件资源的关键角色。它通过节点与属性定义外设的物理特性,如寄存器地址、中断号等。
匹配流程解析
内核初始化时,会将设备树中的节点与已注册的驱动进行匹配。核心依据是驱动中的 of_match_table 成员与设备节点的兼容性字符串(compatible)是否一致。
static const struct of_device_id my_driver_of_match[] = {
    { .compatible = "vendor,my-device", },
    { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, my_driver_of_match);
上述代码定义了驱动支持的设备类型。当内核遍历设备树时,若发现某节点的 compatible = "vendor,my-device",则触发该驱动的 probe 函数。
匹配关键要素对比
要素设备树节点驱动端
兼容性compatible 属性值of_match_table 定义
资源信息reg, interrupts 等platform_get_resource()

2.4 通过设备树传递平台数据与资源信息

在嵌入式Linux系统中,设备树(Device Tree)用于描述硬件平台的结构与资源配置,使内核无需硬编码即可识别外设。
设备树的基本组成
设备树由节点和属性构成,节点代表设备或总线,属性描述其特性。例如:

uart0: serial@101f1000 {
    compatible = "arm,pl011";
    reg = <0x101f1000 0x1000>;
    interrupts = <0 6 4>;
};
其中,compatible 指明驱动匹配标识,reg 定义寄存器地址范围,interrupts 描述中断号与触发类型。
数据解析流程
内核启动时解析设备树,将节点转换为platform_device结构,并通过compatible字段与驱动绑定。该机制实现硬件抽象,提升内核可移植性。

2.5 实战:基于设备树的LED驱动开发

在嵌入式Linux系统中,使用设备树(Device Tree)可以实现硬件描述与驱动代码的解耦。通过在设备树源文件中定义LED节点,可动态配置GPIO引脚属性。
设备树节点定义

leds {
    compatible = "gpio-leds";
    led0: red_led {
        label = "red";
        gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>;
        default-state = "off";
    };
};
上述代码定义了一个红色LED,连接到GPIO1的第18号引脚,高电平点亮。compatible属性匹配驱动程序,gpios指定控制引脚。
驱动加载流程
内核启动时解析设备树,生成platform_device结构。驱动通过of_match_table匹配compatible字符串,调用probe函数完成初始化。
字段作用
label用户空间可见的名称
default-state初始状态,支持on/off/blink

第三章:内核模块编程核心技术

3.1 内核模块的加载机制与生命周期管理

内核模块是Linux系统中可动态加载和卸载的代码单元,能够在不重启系统的情况下扩展内核功能。其加载过程由`insmod`、`modprobe`等工具触发,最终通过系统调用`init_module()`将模块映像插入内核空间。
模块生命周期阶段
  • 加载阶段:解析模块ELF格式,分配内存,执行符号重定位
  • 初始化阶段:调用模块定义的module_init()函数
  • 运行阶段:模块提供服务,如设备驱动、文件系统支持
  • 卸载阶段:通过rmmod调用cleanup_module()释放资源

#include <linux/module.h>
static int __init hello_init(void) {
    printk(KERN_INFO "Hello, kernel!\n");
    return 0;
}
static void __exit hello_exit(void) {
    printk(KERN_INFO "Goodbye, kernel!\n");
}
module_init(hello_init);
module_exit(hello_exit);
上述代码定义了模块的初始化与退出函数。其中__init标记确保初始化代码在完成后被回收内存,__exit在模块不可卸载时自动忽略。printk用于输出内核日志,KERN_INFO为日志级别。
依赖管理与状态跟踪
内核维护模块引用计数,防止在使用中被卸载。多个模块间存在依赖关系时,由modprobe自动解析并加载依赖链。

3.2 模块参数与符号导出的高级用法

在内核模块开发中,合理使用模块参数和符号导出机制可显著提升模块的灵活性与复用性。通过 module_param() 宏,可在加载时动态配置模块行为。
模块参数定义

static int debug = 0;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Enable debug mode (0=off, 1=on)");
上述代码将整型变量 debug 导出为模块参数,权限为 0644,允许在加载时通过 insmod mymodule.ko debug=1 启用调试模式。
符号导出控制
使用 EXPORT_SYMBOL() 可将函数或变量导出供其他模块使用:

void log_event(const char *msg)
{
    printk(KERN_INFO "Event: %s\n", msg);
}
EXPORT_SYMBOL(log_event);
该函数被导出后,其他模块可通过外部声明调用 log_event(),实现跨模块协作。符号导出需谨慎,避免暴露内部实现细节。

3.3 实战:构建可动态加载的GPIO控制模块

在嵌入式Linux系统中,通过内核模块实现对GPIO的灵活控制是驱动开发的关键技能。本节将演示如何编写一个可动态加载的GPIO控制模块。
模块初始化与资源注册

#include <linux/module.h>
#include <linux/gpio.h>>

static unsigned int gpio_led = 18;

static int __init gpio_init(void) {
    gpio_request(gpio_led, "led_gpio");
    gpio_direction_output(gpio_led, 0);
    return 0;
}
该代码段请求GPIO 18并配置为输出模式,用于控制LED。__init标记确保函数仅在初始化时驻留内存。
模块卸载与资源释放
  • 使用gpio_set_value(gpio_led, 1)设置高电平
  • 通过gpio_free(gpio_led)释放GPIO资源
  • 确保__exit函数正确注销设备

第四章:设备树与内核模块深度融合

4.1 利用of_match_table实现驱动精准匹配

在Linux设备驱动开发中,`of_match_table`用于实现设备树节点与驱动的精确匹配。当系统启动时,内核通过比对设备树中的`compatible`属性与驱动中定义的匹配表,自动绑定设备与驱动。
匹配表结构定义
static const struct of_device_id sample_of_match[] = {
    { .compatible = "vendor,sample-device", },
    { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sample_of_match);
该代码定义了一个`of_device_id`数组,其中`compatible`字段必须与设备树中设备节点的`compatible`值一致。内核遍历此表以查找匹配项,成功后触发驱动的`probe`函数。
匹配流程解析
  • 设备树中设备节点声明 compatible 属性
  • 驱动注册时提供 of_match_table 指针
  • 内核执行匹配算法,基于字符串比对
  • 匹配成功则调用驱动 probe 函数初始化硬件

4.2 从设备树中解析设备资源(寄存器、中断)

在Linux内核启动过程中,设备树(Device Tree)用于描述硬件拓扑结构。驱动程序需从中提取关键资源,如内存映射寄存器和中断号。
寄存器资源的获取
通过 `of_iomap()` 函数可将设备树中的寄存器地址映射到内核虚拟地址空间:

struct resource *res;
void __iomem *base;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
上述代码首先获取设备资源结构体,再将其映射为可访问的I/O内存指针,便于后续读写寄存器。
中断资源的解析
使用 `platform_get_irq()` 可自动解析设备树中指定的中断号:
  • 设备树中定义的 interrupts 属性被转换为IRQ编号
  • 返回值可用于请求中断处理函数 request_irq()

4.3 综合实战:带设备树支持的字符设备驱动

在现代嵌入式Linux系统中,设备树(Device Tree)成为描述硬件资源的核心机制。将设备树与字符设备驱动结合,可实现驱动代码与硬件信息的解耦,提升可维护性。
设备树节点定义
在设备树源文件中添加如下节点:

mychar_device: mychar@20000000 {
    compatible = "alientek,mychar";
    reg = <0x20000000 0x1000>;
};
其中,compatible用于匹配驱动,reg指定寄存器起始地址和长度。
驱动中的匹配表
驱动程序通过of_match_table实现自动绑定:

static const struct of_device_id mychar_of_match[] = {
    { .compatible = "alientek,mychar" },
    { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mychar_of_match);
内核在探测设备时会依据compatible字段完成匹配,触发probe函数调用。

4.4 调试技巧:使用device_node接口进行运行时诊断

在Linux设备模型中,`device_node`接口为驱动开发者提供了直接访问设备树节点的能力,支持运行时动态获取硬件配置信息,是调试硬件适配问题的重要手段。
核心接口调用示例

const char *status;
u32 reg_base;

// 获取设备树属性值
status = of_get_property(np, "status", NULL);
if (of_property_read_u32(np, "reg", &reg_base)) {
    printk(KERN_ERR "Missing 'reg' property\n");
}
上述代码通过 `of_get_property` 读取节点属性,`of_property_read_u32` 解析寄存器基地址。若属性缺失,可快速定位设备树配置错误。
常用诊断流程
  • 确认设备节点是否被正确解析(of_node_is_available())
  • 逐项校验关键属性是否存在且格式正确
  • 结合printk输出运行时值,验证与预期一致

第五章:总结与进阶学习建议

持续实践是掌握技术的核心路径
真实项目中遇到的问题远比教程复杂。例如,在优化 Go 服务的并发性能时,使用 sync.Pool 可显著减少内存分配压力:

var bufferPool = sync.Pool{
    New: func() interface{} {
        return make([]byte, 1024)
    },
}

func process(data []byte) {
    buf := bufferPool.Get().([]byte)
    defer bufferPool.Put(buf)
    // 使用 buf 进行临时数据处理
}
构建系统化的学习路线
进阶开发者应关注底层机制与架构设计。以下是推荐的学习方向组合:
  • 深入理解操作系统:进程调度、虚拟内存、文件系统
  • 掌握网络协议栈:TCP 拥塞控制、TLS 握手流程、HTTP/2 多路复用
  • 学习分布式系统模式:如两阶段提交、Raft 一致性算法
  • 参与开源项目:从修复文档错别字到提交核心功能补丁
利用工具链提升效率
现代开发依赖高效的工具协同。以下为典型调试场景的工具搭配方案:
问题类型推荐工具使用场景
内存泄漏pprof分析 Go 程序堆内存分布
延迟突增eBPF + bcc追踪内核级系统调用延迟
服务拓扑混乱Jaeger可视化微服务间调用链
系统性能监控面板示例
NXP Real-time Edge:一站式工业实时边缘计算平台构建指南 在工业自动化与机器人控制领域,实时操作系统(RTOS)与通用Linux生态的结合是满足高确定性响应与丰富功能需求的关键。其核心原理在于通过实时内核补丁(如PREEMPT_RT)、异构多核通信框架(如RPMSG/VirtIO)等技术,将实时任务与通用计算任务在硬件层面进行隔离与协同。这种技术方案的价值在于,它使得开发者能够在同一硬件平台上,同时运行对延迟敏感的实时控制任务(如EtherCAT伺服驱动)和复杂的非实时应用(如AI视觉推理),从而简化系统架构,降低开发与维护成本。典型的应用场景包括工业视觉检测、A 阅读详情

相关推荐

NVIDIA AGX Orin开发板从开箱到AI部署:保姆级环境配置与实战指南

边缘计算作为将数据处理和分析能力下沉至网络边缘的关键技术,其核心在于通过靠近数据源的本地化计算,有效降低延迟、节省带宽并提升响应速度。其技术原理依赖于高性能、低功耗的专用硬件平台,如NVIDIA Jetson系列,结合优化的AI推理框架。这一技术价值在于为机器人、自动驾驶和智能物联网设备提供了实时、可靠的智能决策能力。在应用场景上,边缘AI广泛部署于工业视觉检测、自主导航和实时视频分析等领域。本文聚焦于NVIDIA AGX Orin开发板的实战部署,详细解析了从硬件初始化、系统烧录到核心开发环境搭建的全流程

leonard61306500的专栏 332

NXP Layerscape平台Docker容器部署与高级电源管理实战指南

在嵌入式系统开发中,操作系统级虚拟化与电源管理是提升部署效率与优化系统能效的两大核心技术。容器化技术通过标准化打包与隔离部署,实现了应用环境的快速迁移与一致性保障,而Linux内核的电源管理框架则提供了从CPU频率动态调节到芯片级深度睡眠的精细控制能力。这两项技术的结合,对于需要在资源受限的边缘环境中同时保证服务敏捷性与续航能力的应用场景具有重要价值。本文聚焦于NXP Layerscape高性能ARM64平台,详细阐述了在运行Docker容器的环境下,如何配置与验证包括动态频率调节(DFS)、低功耗模式(L

a631278993的博客 570

嵌入式Linux驱动开发:从基础知识到实践精通

本文还有配套的精品资源,点击获取 简介:嵌入式Linux由于其稳定性、可定制性和丰富资源,在智能设备领域得到广泛应用。掌握嵌入式Linux驱动程序设计对于开发者至关重要。本课程从基础知识点出发,详细介绍了内核接口理解、设备树编程、I/O操作、字符与块设备驱动、网络驱动、电源管理、调试技巧、硬件抽象层、设备模型和模块化编程等关键技能,并通过实际操作实践来强化学习,帮助开发者成...

weixin_36197669的博客 2149

NXP Real-time Edge 2.8:异构多核实时边缘计算软件栈深度解析与实战

在工业自动化和边缘计算领域,实时操作系统(RTOS)和确定性网络是构建高可靠系统的基石。其核心原理在于通过精确的任务调度和中断管理,确保关键任务在严格的时间窗口内完成,从而满足工业控制、机器人等场景对低延迟和确定性的严苛要求。这一技术价值在于,它使得通用计算平台也能胜任传统上由专用硬件完成的实时控制任务,极大地提升了系统的灵活性和集成度。应用场景广泛覆盖从产线机械臂、智能电网到TSN(时间敏感网络)交换机等。NXP的Real-time Edge软件栈正是这一理念的工程实践典范,它基于Yocto项目构建,集成

dfuw13072的博客 409

Linux嵌入式驱动开发实战教程

本文还有配套的精品资源,点击获取 简介:Linux嵌入式驱动开发涉及硬件设备与操作系统内核的紧密结合,让操作系统能高效管理硬件。开发者需精通Linux内核机制、硬件原理和C语言。本课程深入探讨Linux内核与驱动的关系、驱动程序分类、开发流程、嵌入式环境下的特殊考虑以及设计原则,并提供了一系列的学习资源和实验指导,帮助开发者在实践中深入理解驱动开发,并为嵌入式系统开发打下坚...

weixin_33750664的博客 1849

C++11并发与多线程笔记(2) 线程启动、结束,创建线程多法、join,detach

第二节 线程启动、结束,创建线程多法、join,detach 一、范例演示线程运行的开始 程序运行起来,生成一个进程,该进程所属的主线程开始自动运行;当主线程从main()函数返回,则整个进程执行完毕 主线程从main()开始执行,那么我们自己创建的线程,也需要从一个函数开始运行(初始函数),一旦这个函数运行完毕,线程也结束运行 整个进程是否执行完毕的标志是:主线程是否执行完,如果主线程执行完毕了,就代表整个进程执行完毕了,此时如果其他子线程还没有执行完,也会被强行终止【此条有例外,以后会解释】 创建

qq_38231713的博客 1万+

嵌入式Linux驱动开发 01:基础开发与使用

驱动开发是嵌入式Linux中工作比重比较大的一部分。这篇文章将记录下最基本的驱动开发过程。

Naisu的各种笔记 5483

从ADS到SystemVue:当简单链路预算不够用时,我的射频系统级仿真方案升级实录

本文详细介绍了从ADS到SystemVue的射频系统级仿真升级路径,重点分析了基础链路预算在多端口元件和复杂场景下的局限性,并提供了SystemVue在非线性系统验证和跨域协同分析中的优势。通过实际案例展示了如何平滑迁移工具链,提升仿真精度和效率,适用于5G、毫米波雷达等现代射频系统设计。

weixin_34233974的博客 343

嵌入式linux驱动开发-字符设备驱动

驱动字符设备驱动简介字符设备驱动开发步骤驱动模块的加载和卸载 之前在嵌入式系统移植停留了一段时间,枯燥地看uboot、kernel和跟文件系统的源码感觉没有成就感,在这之前已经对嵌入式linux的启动流程有了大体的了解,因此先跳到驱动开发,体验学习一下子哈!!。 Linux 中的三大类驱动:字符设备驱动、块设备驱动和网络设备驱动。 字符设备驱动:IO口的驱动,比如点灯、 I2C、 SPI、音频等。 块设备驱动:存储器设备的驱动,比如 EMMC、 NAND、 SD 卡和 U 盘等存储设备 网络设备驱动:网络驱

平平酱的博客 3652

微调BERT进行中文文本分类任务(Pytorch代码实现)

BERT(Bidirectional Encoder Representation from Transformers)是2018年10月由Google AI研究院提出的一种预训练模型。其模型结构由多层Transformer的Encoder堆叠而成,在大规模语料中进行预训练后,迁移到下游任务,仅进行参数微调训练,就能显著提升性能。本文聚焦于微调中文BERT进行新闻标题分类任务的代码实现。

Iswayzw的博客 1万+

OpenClaw本地部署教程

本文详细介绍了在Windows 11系统上部署OpenClaw与Ollama本地模型的完整流程。主要内容包括:硬件要求说明、Node.js环境配置、Ollama模型安装与定制(重点扩展上下文窗口至32768 tokens)、OpenClaw核心框架安装与对接、常见问题解决(如模型上下文窗口过小报错)以及可选技能扩展和飞书接入方案。部署全程约需1-2小时,强调使用备用设备或虚拟机以确保安全,并提供关键配置参数和排错命令。该方案实现了"数据不出门、推理本地化"的私有化部署目标。

技术引领业务创新 2577

嵌入式Linux视频笔记----驱动开发

https://www.bilibili.com/video/BV1pf4y1974n/?spm_id_from=333.788.videocard.1 基本看完了,基本只看视频没看详细的pdf,试验挑着做,一讲代码就蒙蔽。但还是有了基本的概念,知道驱动相关知识 P1 内核模块基本概念 现代内核派系:宏内核--Linux等、关键功能和服务功能均在内核、效率高、扩展性差;微内核--关键功能在内核,服务功能在用户空间、效率低、扩展性高 内核模块:加载、卸载;入口、出口;信息声明 下面两个实验都是最简.

gzc0319的博客 2279

数字后端零基础入门系列 | Innovus零基础LAB学习Day9

数字后端零基础入门系列 | Innovus零基础LAB学习Day9

weixin_37584728的博客 4577

微处理器与嵌入式设备——Linux下的驱动程序开发

在本次实验中,我们利用已经设计好的硬件环境,在 Linux系统下,设计了驱动程序和测试程序,利用串口拷贝驱动和测试程序,调用测试程序对驱动进行了测试,实现了输入二进制数和开发板LED 灯之间的二进制对应关系。在实验 2 中,我们使用 uart接口读取串口信息并将其返回到串口,进一步的了解了Linux 下的驱动程序设计方法。通过这次实验,我们掌握了Linux系统下设备驱动程序的作用与编写技巧,掌握Linux驱动程序模块加载和卸载的方法,了解串口驱动的原理和工作方式。

qq_45945307的博客 958

MIPI D-PHY TX 一致性测试实例解析 Part 01

汽车电子领域,尤其是ADAS,伴随着摄像头的大规模布局,MIPI信号的使用日益频繁,关于它的验证与分析工作也变得日益关键

一只豌豆象的博客 1万+

vLLM专题(七)-支持的模型列表

vLLM支持跨多种任务的生成式和池化模型。如果一个模型支持多个任务,您可以通过–task参数来设置任务。对于每个任务,我们列出了已在vLLM中实现的模型架构。每个架构旁边,我们列出了一些使用该架构的流行模型。

1259

嵌入式Linux驱动程序开发

嵌入式Linux驱动程序开发 1.设备驱动程序的概念... 2 2.处理器与设备间数据交换方式... 2 21.查询方式... 2 2.2.中断方式... 3 2.3.直接访问内存(DMA)方式... 3 3.驱动程序结构... 3 3.1一个设备驱动程序模块的基本框架... 4 3.1. file_operations结构体... 5 3.2.inode{}和file{}结构体...

jinghuainfo 2260

29、Power BI 中行级安全(RLS)的实现与应用

本文详细介绍了在Power BI中实现行级安全(RLS)的方法,包括静态RLS和动态RLS的实现流程、适用场景及对比分析。通过具体业务场景,展示了如何创建安全角色、定义规则、验证角色、发布模型以及分配成员。此外,还探讨了更复杂的动态RLS场景,如基于父子层次结构的数据访问控制和从外部源获取用户信息的实现方式。文章最后总结了最佳实践建议及未来发展趋势,为企业在Power BI中高效、安全地实施数据访问控制提供了全面指导。

terraform7cloud的博客 195

嵌入式Linux驱动开发(一)——Hello Module驱动程序开发

由于我们设置的默认消息日志为6,而当前控制台日志等级为7所以,default的日志消息打印了,同时KERN_EMERG日志等级为0,所以这个消息日志也打印了。由于我们当前控制台日志等级为7,而KERN_DEBUG日志等级为7,所以在hellomodule_exit函数中的。想要理解这两个宏的作用,那么我们应该找到这两个宏的定义处,在include\linux下的init.h中定义的。make modules:执行Linux顶层Makefile的伪目标,它实现内核模块的源码读取并编译为.ko文件。

FourLeafCloverLLLS的博客 1031

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

嵌入式Linux驱动开发(十二)platform设备驱动实验

基于驱动可重用性考虑,提出驱动分离与分层思想。平台设备驱动就是基于此。

qq_41075961的博客 1214

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

【嵌入式Linux】嵌入式Linux驱动开发基础知识之驱动程序基石

韦东山嵌入式Linux驱动开发基础知识学习笔记 文章中大多内容来自韦东山老师的文档,还有部分个人根据自己需求补充的内容 视频教程地址:https://www.bilibili.com/video/BV14f4y1Q7ti

永远年轻 永远热泪盈眶 2770

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

嵌入式Linux驱动开发基础知识_韦东山——hello驱动程序开发

【代码】嵌入式Linux驱动开发基础知识(一)——hello驱动程序开发。

FourLeafCloverLLLS的博客 1556

最全Linux驱动开发全流程详细解析(持续更新)

Linux驱动开发详细解析

拉依达不拉跨的博客 11万+

嵌入式Linux驱动开发学习笔记

字符设备是 Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的。比如我们最常见的点灯、按键、IIC、SPI,LCD 等等都是字符设备,这些设备的驱动就叫做字符设备驱动。

学好嵌入式的博客 749

Linux嵌入式驱动开发13——ioctl接口(gpio控制使用)

文章目录什么是unlocked_ioctl接口?unlocked_ioctl和read/write函数有什么相同和不同unlocked_ioctl接口命令规则命令的合成宏与分解宏合成宏分解宏测试程序使用_IOmodule_leds.cMakefileapp.c结果使用_IOW使用_IOR实验结果完整代码module_leds.capp.c 我们从平台总线模型,然后到pinctrl和gpio子系统,会发现步骤逐渐的规范,代码也逐渐的简单,也越来越能体会到linux屏蔽底层硬件的优势。 在之前的代码中,在wri

“逛丢一只鞋”的博客 4771

嵌入式Linux驱动开发简介

Linux驱动开发大体描述

时光の尘的博客 955
上一篇: 【多语言代码审查终极指南】:揭秘高效自动化工具与人工协同的5大核心策略
下一篇: 【ROS 2实时性优化终极指南】:C++底层加速与Python节点调度的黄金组合
quickcode
博客等级 码龄19年 146粉丝 1996原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值