嵌入式底层驱动开发笔记2

字符设备驱动开发代码备注

#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/device.h> /* device_create()*/

#include "memdev.h"

static int mem_major = MEMDEV_MAJOR;

module_param(mem_major, int, S_IRUGO);

struct mem_dev *mem_devp; /*设备结构体指针*/

struct cdev cdev; 

/*文件打开函数*/
int mem_open(struct inode *inode, struct file *filp)
{
    struct mem_dev *dev;
    
    /*获取次设备号*/
    int num = MINOR(inode->i_rdev);

    if (num >= MEMDEV_NR_DEVS) 
            return -ENODEV;
    dev = &mem_devp[num];
    
    /*将设备描述结构指针赋值给文件私有数据指针*/
    filp->private_data = dev;
    
    return 0; 
}

/*文件释放函数*/
int mem_release(struct inode *inode, struct file *filp)
{
  return 0;
}

/*读函数*/
static ssize_t mem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
  unsigned long p =  *ppos;//p为当前读写位置
  unsigned int count = size;//一次读取的大小
  int ret = 0;
  struct mem_dev *dev = filp->private_data; /*获得设备结构体指针*/

  /*判断读位置是否有效*/
  if (p >= MEMDEV_SIZE)//是否超出读取获围
    return 0;
  if (count > MEMDEV_SIZE - p)//如果count大于可读取的范围
    count = MEMDEV_SIZE - p;// 缩小读取范围。


  /*读数据到用户空间*/
  if (copy_to_user(buf, (void*)(dev->data + p), count))//返回buf,读取位置,读取数量
  {
    ret =  - EFAULT;
  }
  else
  {
    *ppos += count;//将文件当前位置向后移
    ret = count;//返回实际读取字节数
    
    printk(KERN_INFO "read %d bytes(s) from %d\n", count, p);
  }

  return ret;//返回实际读取字节数,判断读取是否成功
}

/*写函数*/
static ssize_t mem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
  unsigned long p =  *ppos;//p为当前读写位置
  unsigned int count = size;//一次读取的大小
  int ret = 0;
  struct mem_dev *dev = filp->private_data; /*获得设备结构体指针*/
  
  /*分析和获取有效的写长度*/
  if (p >= MEMDEV_SIZE)//如果超出读取获围,返回0.
    return 0;
  if (count > MEMDEV_SIZE - p)//如果count大于可读取的范围
    count = MEMDEV_SIZE - p;// 缩小读取范围。
    
  /*从用户空间写入数据*/
  if (copy_from_user(dev->data + p, buf, count))
    ret =  - EFAULT;
  else
  {
    *ppos += count;//将文件当前位置向后移
    ret = count;//返回实际读取字节数
    
    printk(KERN_INFO "written %d bytes(s) from %d\n", count, p);
  }

  return ret;
}

/* seek文件定位函数 */
static loff_t mem_llseek(struct file *filp, loff_t offset, int whence)//作改变文件中的当前读/写位置, 并且新位置作为(正的)返回值在测试程序中要重新定位文件位置,whence这里被设置为 SEEK_SET
{ 
    loff_t newpos;

    switch(whence) {
      case 0: /* SEEK_SET */
        newpos = offset;//从文件头开始定位
        break;

      case 1: /* SEEK_CUR */
        newpos = filp->f_pos + offset;//从文件中间定位
        break;

      case 2: /* SEEK_END */
        newpos = MEMDEV_SIZE -1 + offset;//从文件尾开始定位,由于是从0开始,所以要减1
        break;

      default: /* can't happen */
        return -EINVAL;
    }
    if ((newpos<0) || (newpos>MEMDEV_SIZE))
    	return -EINVAL;
    	
    filp->f_pos = newpos; //返回当前文件位置
    return newpos;

}

/*文件操作结构体*/
static const struct file_operations mem_fops =
{
  .owner = THIS_MODULE,
  .llseek = mem_llseek,
  .read = mem_read,
  .write = mem_write,
  .open = mem_open,
  .release = mem_release,
};

/*设备驱动模块加载函数*/
static int memdev_init(void)//初始化模块
{
	struct class *myclass;
  int result;
  int i;

  dev_t devno = MKDEV(mem_major, 0);//MKDEV是将主设备号和次设备号转换为dev_t类型数据,参数mem_major在头文件中预设

  /* 静态申请设备号*/
  if (mem_major)//memdev.h 中定义了设备号。为静态分配主设备号
    result = register_chrdev_region(devno, 2, "memdev");//devno为主设备号,共申请两个连续的设备,设备名为"memdev
  else  /* 动态分配设备号 */
  {
    result = alloc_chrdev_region(&devno, 0, 2, "memdev"); //&devno作为一个输出参数,次设备号从0开始分配,申请2个设备,设备名为"memdev"
    mem_major = MAJOR(devno);//获取动态分配到的主设备号
  }  
  
  if (result < 0)//result返回0时为申请成功,反加负值为申请失败。
    return result;

  /*初始化cdev结构*/
  cdev_init(&cdev, &mem_fops); //初始化cdev结构,将结构体cdev和mem_fops绑定起来
  cdev.owner = THIS_MODULE;//驱动引用计数,作用是这个驱动正在使用的时候,再次用inmod命令时,出现警告提示
  cdev.ops = &mem_fops;
  
  /* 注册字符设备 */
  cdev_add(&cdev, MKDEV(mem_major, 0), MEMDEV_NR_DEVS);
   
  /* 为设备描述结构分配内存*/
  mem_devp = kmalloc(MEMDEV_NR_DEVS * sizeof(struct mem_dev), GFP_KERNEL);
  if (!mem_devp)    /*申请失败*/
  {
    result =  - ENOMEM;
    goto fail_malloc;
  }
  memset(mem_devp, 0, sizeof(struct mem_dev));//新申请的内存做初始化工作
  
  /*为设备分配内存*/
  for (i=0; i < MEMDEV_NR_DEVS; i++) 
  {
        mem_devp[i].size = MEMDEV_SIZE;//为设备分配内存
        mem_devp[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);//分配内存给两个设备
        memset(mem_devp[i].data, 0, MEMDEV_SIZE);//初始化新分配到的内存
  }
  /*自动创建设备文件*/
	myclass = class_create(THIS_MODULE,"test_char"); /*在sys下创建类目录/sys/class/test_char*/
	device_create(myclass, NULL, MKDEV(mem_major,0), NULL, "memdev0");   
  return 0;

  fail_malloc: 
  unregister_chrdev_region(devno, 1);//如果申请失败,注销设备
  
  return result;
}

/*模块卸载函数*/
static void memdev_exit(void)
{
  cdev_del(&cdev);   /*注销设备*/
  kfree(mem_devp);     /*释放设备结构体内存*/
  unregister_chrdev_region(MKDEV(mem_major, 0), 2); /*释放设备号*/
}

MODULE_AUTHOR("David Xie"); 
MODULE_LICENSE("GPL");

module_init(memdev_init);//注册模块加载函数
module_exit(memdev_exit);//注册模块卸载函数
#include <stdio.h>

int main()
{
	FILE *fp0 = NULL;
	char Buf[4096];
	
	/*初始化Buf*/
	strcpy(Buf,"Mem is char dev!");
	printf("BUF: %s\n",Buf);
	
	/*打开设备文件*/
	fp0 = fopen("/dev/memdev0","r+");
	if (fp0 == NULL)
	{
		printf("Open Memdev0 Error!\n");
		return -1;
	}
	
	/*写入设备*/
	fwrite(Buf, sizeof(Buf), 1, fp0);
	
	/*重新定位文件位置(思考没有该指令,会有何后果)*/
	fseek(fp0,0,SEEK_SET);//调用mem_llseek()定位,使文件指针移回到开始位置
	
	/*清除Buf*/
	strcpy(Buf,"Buf is NULL!");//覆盖以前的值,以防读不出来时无法判断
	printf("BUF: %s\n",Buf);
	
	
	/*读出设备*/
	fread(Buf, sizeof(Buf), 1, fp0);
	
	/*检测结果*/
	printf("BUF: %s\n",Buf);
	
	return 0;	

}
├ │ ├01 - 从零开始认识开发板1.mp4 │ ├02 - 从零开始认识开发2.mp4 │ ├03 - 从零开始认识开发板3.mp4 │ ├04 - 从零开始认识开发板4.mp4 │ └05 - 从零开始认识开发板5.mp4 ├ │ ├01 - 说在前面的话1.mp4 │ ├02 - 说在前面的话2.mp4 │ ├03 - 说在前面的话3.mp4 │ ├04 - 说在前面的话4.mp4 │ ├05 - 计算机组成原理概述1 .mp4 │ ├06 - 计算机组成原理概述2 .mp4 │ ├07 - 计算机组成原理概述3 .mp4 │ ├08 - Linux基础及操作系统框架1.mp4 │ ├09 - Linux基础及操作系统框架2.mp4 │ ├10 - Linux基础及操作系统框架3.mp4 │ ├11 - Linux基础及操作系统框架4.mp4 │ ├12 - Shell命令机制1.mp4 │ ├13 - Shell命令机制2.mp4 │ ├14 - Shell命令机制3.mp4 │ ├15 - Shell命令机制4.mp4 │ ├16 - Linux命令类库机制及常用命令_命令操练1.mp4 │ ├17 - 命令操练2.mp4 │ ├18 - 命令操练3.mp4 │ ├19 - 命令操练4.mp4 │ ├20 - 命令操练5.mp4 │ ├21 - 命令操练6.mp4 │ ├22 - 命令操练7.mp4 │ ├23 - 命令操练8.mp4 │ ├24 - 命令操练9.mp4 │ ├25 - 命令操练10.mp4 │ ├26 - 命令操练11.mp4 │ ├27 - Linux应用程序安装及卸载1.mp4 │ ├28 - Linux应用程序安装及卸载2.mp4 │ ├29 - Linux应用程序安装及卸载3.mp4 │ ├30 - Linux应用程序安装及卸载4.mp4 │ ├31 - Linux应用程序安装及卸载5.mp4 │ ├32 - Linux服务程序的安装及配置1.mp4 │ ├33 - Linux服务程序的安装及配置2.mp4 │ ├34 - Linux服务程序的安装及配置3.mp4 │ ├35 - Linux服务程序的安装及配置4.mp4 │ ├36 - Vi的设计思想及使用1.mp4 │ ├37 - Vi的设计思想及使用2.mp4 │ └38 - Vi的设计思想及使用3.mp4 ├ │ ├001 - GNU开发环境基础1.mp4 │ ├002 - GNU开发环境基础2.mp4 │ ├003 - GNU开发环境基础3.mp4 │ ├004 - GNU开发环境基础4.mp4 │ ├005 - GNU开发环境基础_gcc编译1.mp4 │ ├006 - GNU开发环境基础_gcc编译2.mp4 │ ├007 - GNU开发环境基础_gcc编译3.wmv │ ├008 - GNU开发环境基础_gdb.mp4 │ ├009 - GNU开发环境基础_Makefile1.mp4 │ ├10 - GNU开发环境基础_Makefile2.wmv │ ├11 - GNU开发环境基础_Makefile3.wmv │ ├12 - GNU开发环境基础_Autotools1.mp4 │ ├14 - GNU开发环境基础_Autotools3.mp4 │ ├15 - GNU开发环境基础_EclipseForLinux.mp4 │ ├16 - Linux高级程序_IO操作1.mp4 │ ├17 - Linux高级程序_IO操作2.wmv │ ├18 - Linux高级程序_IO操作3.mp4 │ ├19 - Linux高级程序_IO操作4.wmv │ ├20 - Linux高级程序_IO操作5.mp4 │ ├21 - Linux高级程序_IO操作6.wmv │ ├22 - Linux高级程序_IO操作7.mp4 │ ├23 - Linux高级程序_IO操作8.wmv │ ├24 - Linux高级程序_IO操作9.mp4 │ ├25 - Linux高级程序_IO操作_lock1.wmv │ ├26 - Linux高级程序_IO操作_lock2.wmv │ ├27 - Linux高级程序_IO操作_lock3.mp4 │ ├28 - Linux高级程序_IO操作_dir1.mp4 │ ├29 - Linux高级程序_IO操作_dir2.wmv │ ├30 - Linux高级程序_IO操作_dir3.wmv │ ├31 - Linux高级程序_进程管理1.mp4 │ ├32 - Linux高级程序_进程管理2.mp4 │ ├33 - Linux高级程序_进程管理3.wmv │ ├34 - Linux高级程序_进程管理4.wmv │ ├35 - Linux高级程序_进程管理5.mp4 │ ├36 - Linux高级程序_进程管理6.mp4 │ ├37 - Linux高级程序_进程管理_Daemon1.avi │ ├38 - Linux高级程序_进程管理_Daemon2.avi │ ├39 - Linux高级程序_进程管理_Daemon3.mp4 │ ├40 - Linux高级程序_进程间通信_Pipe1.avi │ ├41 - Linux高级程序_进程间通信_Pipe2.mp4 │ ├42 - Linux高级程序_进程间通信_Pipe3.avi │ ├43 - Linux高级程序_进程间通信_Fifo1.mp4 │ ├44 - Linux高级程序_进程间通信_Fifo2.mp4 │ ├45 - Linux高级程序_进程间通信_Signal1.avi │ ├46 - Linux高级程序_进程间通信_Signal2.avi │ ├47 - Linux高级程序_进程间通信_Signal3.mp4 │ ├48 - Linux高级程序_进程间通信_SHM1.avi │ ├49 - Linux高级程序_进程间通信_SHM2.avi │ ├50 - Linux高级程序_进程间通信_SHM3.mp4 │ ├51 - Linux高级程序_进程间通信_MsgQueue1.avi │ ├52 - Linux高级程序_进程间通信_MsgQueue2.avi │ ├53 - Linux高级程序_进程间通信_Semaphore1.mp4 │ ├54 - Linux高级程序_进程间通信_Semaphore2.avi │ ├55 - 线程_Thread1.avi │ ├56 - 线程_Thread2.mp4 │ ├57 - 线程_Thread3.mp4 │ ├58 - 网络编程_Concept1.mp4 │ ├59 - 网络编程_Concept2.avi │ ├60 - 网络编程_Concept3.mp4 │ ├61 - 网络编程_Concept4.mp4 │ ├62 - 网络编程_TCPIP编程基础1.mp4 │ ├63 - 网络编程_TCPIP编程基础2.avi │ ├64 - 网络编程_TCPIP编程基础3.avi │ ├65 - 网络编程_TCPIP编程基础4.mp4 │ ├66 - 网络编程_TCPIP编程基础5.avi │ ├67 - 网络编程_TCPIP编程基础6.mp4 │ ├68 - 网络编程_HTTP原理1.mp4 │ ├69 - 网络编程_HTTP原理2.avi │ ├70 - 网络编程_HTTP原理3.avi │ ├71 - 网络编程_HTTP原理4 .mp4 │ ├72 - 网络编程_HTTP原理5.mp4 │ ├73 - 网络编程_HTTP原理6.mp4 │ ├74 - 网络编程_Socket内核跟踪1.avi │ └75 - 网络编程_Socket内核跟踪2.mp4 ├ │ ├01 - ARM准备工作及熟悉开发板1.mp4 │ ├02 - ARM准备工作及熟悉开发2.mp4 │ ├03 - ARM准备工作及熟悉开发板3.avi │ ├04 - ARM准备工作及熟悉开发板4.mp4 │ ├05 - 原理图及电路图1.mp4 │ ├06 - 原理图及电路图2.avi │ ├07 - 原理图及电路图3.mp4 │ ├08 - ARM世界 .mp4 │ ├09 - 开发环境搭建1.mp4 │ ├10 - 开发环境搭建2.avi │ ├100 - 中断流程代码1.mp4 │ ├101 - 中断流程代码2.avi │ ├102 - 中断流程代码3.mp4 │ ├103 - IIC协议介绍1.avi │ ├104 - IIC协议介绍2.mp4 │ ├105 - IIC协议介绍3.mp4 │ ├106 - IIC协议介绍4.avi │ ├107 - IIC协议介绍5.mp4 │ ├108 - IIC协议介绍6.mp4 │ ├109 - watchdog介绍1.mp4 │ ├11 - 补充Linux装Sourceinsight.mp4 │ ├110 - watchdog介绍2.mp4 │ ├111 - RTC介绍.avi │ ├112 - PWM介绍1.mp4 │ ├113 - PWM介绍2.avi │ ├114 - PWM介绍3.mp4 │ ├115 - ADC介绍1.avi │ ├116 - ADC介绍2.mp4 │ ├117 - ARM硬件接口项目介绍1.avi │ ├118 - ARM硬件接口项目介绍2.mp4 │ ├119 - ARM硬件接口项目介绍3.avi │ ├12 - 补充MiniTool烧写开发板-11.30更新工具.avi │ ├120 - ARM硬件接口项目介绍4.mp4 │ ├121 - ARM硬件接口项目介绍5.avi │ ├122 - ARM硬件接口项目介绍6.mp4 │ ├123 - ARM硬件接口项目介绍7.mp4 │ ├13 - ARM体系结构-学习方法.mp4 │ ├14 - ARM体系结构-处理器和名词1.mp4 │ ├15 - ARM体系结构-处理器和名词2.avi │ ├16 - ARM体系结构-工具和交叉工具链.mp4 │ ├17 - 处理器模式和片内寄存器1.avi │ ├18 - 处理器模式和片内寄存器2.mp4 │ ├19 - 处理器模式和片内寄存器3.avi │ ├20 - 处理器模式和片内寄存器4.mp4 │ ├21 - ARM汇编寻址模式1.mp4 │ ├22 - ARM汇编寻址模式2.avi │ ├23 - ARM汇编寻址模式3.mp4 │ ├24 - ARM汇编算数操作1.mp4 │ ├25 - ARM汇编算数操作2.avi │ ├26 - ARM汇编算数操作3.mp4 │ ├27 - ARM汇编算数操作4.mp4 │ ├28 - ARM汇编内存操作1.avi │ ├29 - ARM汇编内存操作2.mp4 │ ├30 - 跳转指令及其它1.mp4 │ ├31 - 跳转指令及其它2.avi │ ├32 - ARM汇编伪指令1.mp4 │ ├33 - ARM汇编伪指令2.avi │ ├34 - ARM汇编伪指令3.avi │ ├35 - ARM汇编伪指令4.mp4 │ ├36 - 混合编程1.avi │ ├37 - 混合编程2.mp4 │ ├38 - ARM硬件基础概述1.avi │ ├39 - ARM硬件基础概述2 .mp4 │ ├40 - ARM硬件基础概述3 .mp4 │ ├41 - ARM硬件基础-SIMD&NEON;.mp4 │ ├42 - ARM硬件基础-Cache1.avi │ ├43 - ARM硬件基础-Cache2.mp4 │ ├44 - ARM硬件基础-MMU1.mp4 │ ├45 - ARM硬件基础-MMU2(1).mp4 │ ├45 - ARM硬件基础-MMU2.mp4 │ ├46 - ARM硬件基础-MMU3.mp4 │ ├47 - ARM异常及中断1 .avi │ ├48 - ARM异常及中断2.mp4 │ ├49 - 第一个裸板试验1.avi │ ├50 - 第一个裸板试验2.mp4 │ ├51 - S5PV210启动原理1.mp4 │ ├52 - S5PV210启动原理2.avi │ ├53 - ARM硬件接口GPIO1.mp4 │ ├54 - ARM硬件接口GPIO2.avi │ ├55 - ARM硬件接口GPIO3.mp4 │ ├56 - ARM硬件接口GPIO4.avi │ ├57 - ARM硬件接口GPIO5.mp4 │ ├58 - ARM硬件接口开发前言.mp4 │ ├59 - ARM硬件接口开发简介.avi │ ├60 - 确定开发板资源1.avi │ ├61 - 确定开发板资源2.mp4 │ ├62 - 确定开发板资源3.avi │ ├63 - 确定开发板资源4.mp4 │ ├64 - 驱动开发板资源5.avi │ ├65 - 驱动开发板资源6.mp4 │ ├66 - 驱动开发板资源7.mp4 │ ├67 - bootloader概述1.mp4 │ ├68 - bootloader概述2 .avi │ ├69 - bootloader概述3.avi │ ├70 - bootloader概述4.mp4 │ ├71 - bootloader概述5.mp4 │ ├72 - C5工程搭建Makefile1.mp4 │ ├73 - C5工程搭建Makefile2.avi │ ├74 - C5工程搭建Makefile3.mp4 │ ├75 - 工程搭建链接脚本录像1.mp4 │ ├76 - 工程搭建链接脚本录像2.avi │ ├77 - 工程搭建C代码点灯录像1.avi │ ├78 - 工程搭建C代码点灯录像2.avi │ ├79 - 工程搭建C代码点灯录像3.mp4 │ ├80 - 通信模型介绍录像1.mp4 │ ├81 - 通信模型介绍录像2.avi │ ├82 - UART协议介绍录像1.mp4 │ ├83 - UART协议介绍录像2.avi │ ├84 - UART协议介绍录像3.avi │ ├85 - UART控制器介绍录像1.mp4 │ ├86 - UART控制器介绍录像2.mp4 │ ├87 - 通过串口发送一个字符录像1.mp4 │ ├88 - 通过串口发送一个字符录像2.avi │ ├89 - 通过串口发送一个字符录像3.avi │ ├90 - 通过串口发送一个字符录像4.mp4 │ ├91 - 通过串口发送一个字符串1.avi │ ├92 - 通过串口发送一个字符串2.mp4 │ ├93 - 中断介绍1.avi │ ├94 - 中断介绍2.mp4 │ ├95 - 中断介绍3.avi │ ├96 - 中断介绍4.mp4 │ ├97 - 中断初始化代码1.mp4 │ ├98 - 中断初始化代码2.avi │ └99 - 中断初始化代码3.mp4 ├ │ ├01 - 开篇的话1.mp4 │ ├02 - 开篇的话2.mp4 │ ├03 - 开篇的话3.mp4 │ ├04 - 内核开发初探1.mp4 │ ├05 - 内核开发初探2.avi │ ├06 - 内核开发初探3.mp4 │ ├07 - Linux内核的基本概念1.mp4 │ ├08 - Linux内核的基本概念2.avi │ ├09 - Linux内核的基本概念3.avi │ ├10 - Linux内核的基本概念4.mp4 │ ├11 - Linux内核的基本概念5.mp4 │ ├12 - Linux驱动程序开发基础1.avi │ ├13 - Linux驱动程序开发基础2.mp4 │ ├14 - Linux驱动程序开发基础3.mp4 │ ├15 - Linux驱动程序开发基础4.avi │ ├16 - Linux驱动程序开发基础5.mp4 │ ├17 - LED设备驱动1.mp4 │ ├18 - LED设备驱动2.mp4 │ ├19 - LED设备驱动3.avi │ ├20 - LED设备驱动4.mp4 │ ├21 - LED设备驱动5.avi │ ├22 - RTC驱动1.mp4 │ ├23 - RTC驱动2.avi │ ├24 - RTC驱动3.avi │ ├25 - RTC驱动4.mp4 │ ├26 - 电容触摸屏驱动1.avi │ ├28 - 电容触摸屏驱动3.avi │ ├29 - 电容触摸屏驱动4.mp4 │ ├30 - 网络设备驱动1.mp4 │ ├31 - 网络设备驱动2.avi │ ├32 - 网络设备驱动3.avi │ ├33 - 网络设备驱动4.mp4 │ ├34 - 网络设备驱动5.avi │ ├35 - 网络设备驱动6.mp4 │ ├36 - 声卡驱动1.mp4 │ ├37 - 声卡驱动2.avi │ ├38 - 声卡驱动3.avi │ ├39 - 声卡驱动4.mp4 │ ├40 - 声卡驱动5.mp4 │ ├41 - 声卡驱动6.mp4 │ ├42 - LCD驱动1.mp4 │ ├43 - LCD驱动2.mp4 │ ├44 - LCD驱动3.avi │ ├45 - LCD驱动4.mp4 │ ├46 - LCD驱动5.avi │ ├47 - LCD驱动6.avi │ ├48 - LCD驱动7.mp4 │ ├49 - LCD驱动8.mp4 │ ├50 - LCD驱动9.avi │ ├51 - LCD驱动10.mp4 │ ├52 - nandflash驱动1.mp4 │ ├53 - nandflash驱动2.mp4 │ ├54 - nandflash驱动3.avi │ ├55 - nandflash驱动4.avi │ ├56 - nandflash驱动5.mp4 │ ├57 - nandflash驱动6.mp4 │ └58 - 驱动课程总结提高.mp4 ├ │ ├linux-3.0.8.tiny210.ok.tar │ ├readme.txt │ ├Sundy-AndroidLowLevel.mmap │ ├tiny210.uboot-2011.06.last.tar │ ├tiny210.uboot-2011.06.ok.tar │ ├底层课程资料包.zip │ ├ │ │ ├EABI-4.3.3_EmbedSky_20100610.tar.bz2 │ │ ├gdb-6.8a.tar.bz2 │ │ ├hypertrm超级终端支持Win7.rar │ │ ├putty.zip │ │ └SecureCRT.rar
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

躺尸研究员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值