精华内容
下载资源
问答
  •  我们也可以不使用外设功能(硬件)的定时器,而是通过软件来计算时间。下面通过图2来说明使用软件来定时的示例,图中假设循环(重复)部分的处理需要费时1μs(微秒:100万分之1秒)。由此可以计算出该循环部分...
  •  我们也可以不使用外设功能(硬件)的定时器,而是通过软件来计算时间。下面通过图2来说明使用软件来定时的示例,图中假设循环(重复)部分的处理需要费时1μs(微秒:100万分之1秒)。由此可以计算出该循环部分...
  • 基于JAVA EE的BS应用,前端使用IE浏览器,需要通过串口与pos、地磅、显示屏等外设进行通信。 目前与串口应用基本上都是一个本地应用,用vc、vb、delphi等开发工具开发,使用ie直接与com 通信的案例非常少。 ...
    场景:
    基于JAVA EE的BS应用,前端使用IE浏览器,需要通过串口与pos、地磅、显示屏等外设进行通信。
    目前与串口应用基本上都是一个本地应用,用vc、vb、delphi等开发工具开发,使用ie直接与com
    通信的案例非常少。

    因为项目的软件架构风格不能改变,决定了必须用IE与com通信,这种情况下,采用ActiveX的方式
    成为不多的选择之一

    1环境
    后台就不说了,没有什么关系,下面是前端的环境
    操作系统:win7(32、64)、xp
    浏览器:IE 8
    ACTIVEX:MSCOMM
    html控制:javascript

    2安装
    主要是mscomm控件的安装,
    针对32、64位不同的版本,把ocx文件放在system32目录下(其他位置貌似也可以)
    以管理员身份运行cmd.exe
    运行regsvr32 mscomm.ocx

    3应用
    html<object>
    <object classid="clsid:648A5600-2C6E-101B-82B6-000000000014" id=MSComm1 codebase="MSCOMM32.OCX" type="application/x-oleobject" >
    <param name="CommPort" value="4" /> <!-- 端口号 -->
    <param name="DTREnable" value="1" />
    <param name="Handshaking" value="0" />
    <param name="InBufferSize" value="1024" />
    <param name="InputLen" value="0" />
    <param name="NullDiscard" value="0" />
    <param name="OutBufferSize" value="512" />
    <param name="ParityReplace" value="?" />
    <param name="RThreshold" value="1" /> <!-- -->
    <param name="RTSEnable" value="1" />
    <param name="SThreshold" value="2" />
    <param name="EOFEnable" value="0" />
    <param name="InputMode" value="1" /><!-- binary 1,ascii 0 -->
    <param name="DataBits" value="8" />
    <param name="StopBits" value="1" />
    <param name="BaudRate" value="9600" />
    <param name="Settings" value="9600,N,8,1" /> <!-- 波特率,校验位等 -->
    </object>

    4异步通信
    串口通信本来就是异步通信,类似于以太网的双工工作,发不影响收的过程。
    与前台的交互分成两个过程:
    a:发送,只管数据发送成功就可以了
    b:接收,接收到数据会触发响应事件,接收到完整报文后触发前台的处理函数。但是这里有一个很重要的问题,一个完整的报文是13个字节,
    接收的时候有可能是一次接收到5个, 下一次接收到8个,完成一个完整的报文,需要靠报文的开头、结尾字符去认定一个完整的报文。

    5、JS不可见字符的严重问题
    正常情况下,控件接收到一个报文会赋值给js的变量(字符串),要发送的时候需要把要发送的数据在JS中转换成字符串,传给控件。
    但是,由于JS是弱类型的语言,没有byte的概念,在赋值过程中,部分不可见字符(不仅仅是ascii),入0XEB,就会被转换成0X3F,
    丢失该字节的表征意义。
    解决办法:
    a:修改报文都用可见字符
    b:再写一个控件,接收mscomm的数据后进行进行转码,然后赋值给js变量,反之亦然(本系统采用此方法)

    主要方法:
    $('MSComm1').PortOpen ,可赋值,可取值
    if ($('MSComm1').PortOpen == false) {
    $('MSComm1').PortOpen = true;
    }
    $('MSComm1').Output ,发送指定的内容,在js中会把所有内容转变成字符串,发给mscomm
    [align=center] $('MSComm1').Output = $("tb_send").value);[/align]
    $('MSComm1').Input ,接收到的内容,本意是一个字节数组,赋值给js后会变成一个字符串
    [align=center]var v=$('MSComm1').Input;[/align]
    $('MSComm1').CommEvent ,mscomm事件,在发送、接收,打开、关闭端口都会触发,是异步控制的源头
    [align=center]switch($('MSComm1').CommEvent){
    case 1:{ break;} //发送事件
    case 2: { Receive();break;} //接收事件
    default: alert("Event Raised!"+$('MSComm1').CommEvent);;
    }[/align]
    发送二进制时的几个有用的js方法
    String.fromCharCode(arr[i]):把数字(ascii码)作为unicode编码,转换成一个string类型的字符
    str.charCodeAt(i).toString(16):把一个字符转换成unicode,并且用16进制显示

    4Q&A
    Q:发送0x02怎么办,怎么拼到发送字符串里面
    A:str=str + String.fromCharCode(0x02)

    Q:如何显示收到的字符串中的特殊字符,如0x02
    A:str.charCodeAt(i).toString(16)
    展开全文
  • 操作系统-CPU与外设交互方式 文章目录操作系统-CPU与外设交互方式1. 查询方式2. 无条件传输方式3. 中断方式4. 通道方式5....1. 查询方式 ​ 查询方式是一种异步交互方式...交互必须通过CPU的参与。 2. 无条件传输方式 ​

    操作系统-CPU与外设交互方式

    1. 查询方式

    ​ 查询方式是一种异步交互方式
    ​ 外设的接口处有Ready标志位,CPU想要和外设之间进行数据交互,就要先查询接口的标志位
    询问外设是否准备就绪,如果没有准备就绪,CPU一会儿再来访问;
    ​ 如果外设准备就绪,进行数据传输。
    ​ 特点:由程序发起IO请求,并且等待完成;交互必须通过CPU的参与。

    2. 无条件传输方式

    ​ 无条件传输方式是一种同步交互方式
    ​ 这种操作方式需要外设与CPU进行过完美的同步,
    ​ 保证每次CPU来读的时候,外设的数据都已经准备好了。
    ​ 每次CPU来写的时候,外设准备好了被写入数据。
    ​ 主要用于:外设的时钟周期已知且稳定的场景。

    3. 中断方式

    ​ 当外设准备好发送数据或者接收数据的时候,向操作系统发出中断申请
    ​ CPU放下手中的工作,保存上下文,进行中断响应
    ​ 中断响应结束以后,恢复上下文进行原来的工作。
    ​ 特点:
    ​ 在外设进行准备的过程中,CPU可以先不管外设,和外设并发的工作。
    ​ 缺点:
    ​ 如果IO交互太频繁,中断次数太频繁,CPU需要多次中断,耗费CPU资源

    4. 通道方式

    ​ 通道是一种用来控制内存和外设交互的专门部件
    ​ 通道有自己独立的指令系统,可以脱离CPU独立运行,也可以受控于CPU。
    ​ 常用在大型计算机中。
    ​ 特点:
    ​ IO能力强,以内存为中心,直接与外设进行数据交换,传输过程几乎不需要CPU参与

    5. DMA方式

    当前微机使用广泛的一种方式
    ​ DMA 全称 Direct Memory Access, 直接内存访问
    ​ DMAC :C表示Controller,直接内存访问控制器
    ​ 核心原理:
    ​ CPU把总线控制权交给DMAC,进入DMA方式,完成数据传输之后,DMAC交还总线控制权。
    特点:开始和结束的时候,向CPU交换总线控制权数据传输过程不需要CPU介入
    ​ 基本传输过程:

    1. 外设有DMA需求并且准备就绪,就向DMAC发出请求信号
    2. DMAC收到外设的请求信号之后,向CPU发出总线请求信号
    3. CPU接到总线请求信号之后,如果允许DMA传输,则会在当前总线周期结束之后,发出DMA响应信号,让出总线控制权
    4. DMAC获得对总线的控制权,向外设发出应答信号,通知外设可以进行传输
    5. 进行数据传输
    6. 传输完成之后,DMAC向CPU发出撤销总线控制权请求,CPU收到信号之后,收回总线控制权
    
    展开全文
  • 我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。 Linux内核访问外设I/O内存资源的方式...

    我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。

      Linux内核访问外设I/O内存资源的方式有两种:动态映射(ioremap)和静态映射(map_desc)

      一、动态映射(ioremap)方式

      动态映射方式是大家使用了比较多的,也比较简单。即直接通过内核提供的ioremap函数动态创建一段外设I/O内存资源到内核虚拟地址的映射表,从而可以在内核空间中访问这段I/O资源。

      Ioremap宏定义在asm/io.h内:

      #defineioremap(cookie,size)          __ioremap(cookie,size,0)

      __ioremap函数原型为(arm/mm/ioremap.c)

      void __iomem *__ioremap(unsigned long phys_addr, size_t size, unsigned long

      flags);

      phys_addr:要映射的起始的IO地址

      size:要映射的空间的大小

      flags:要映射的IO空间和权限有关的标志

      该函数返回映射后的内核虚拟地址(3G-4G).接着便可以通过读写该返回的内核虚拟地址去访问之这段I/O内存资源。

      举一个简单的例子: (取自s3c2410iis音频驱动)

      比如我们要访问s3c2410平台上的I2S寄存器查看datasheet 知道IIS物理地址为0x55000000

      我们把它定义为宏S3C2410_PA_IIS,如下:

      #define S3C2410_PA_IIS    (0x55000000)

      若要在内核空间(iis驱动)中访问这段I/O寄存器(IIS)资源需要先建立到内核地址空间的映射:

      our_card->regs= ioremap(S3C2410_PA_IIS,0x100);

      if(our_card->regs == NULL) {

      err = -ENXIO;

      goto exit_err;

      }

      创建好了之后,我们就可以通过readl(our_card->regs)writel(value, our_card->regs)IO接口函数去访问它。

      二、静态映射(map_desc)方式

      下面重点介绍静态映射方式即通过map_desc结构体静态创建I/O资源映射表。

      内核提供了在系统启动时通过map_desc结构体静态创建I/O资源到内核地址空间的线性映射表(page table)的方式,这种映射表是一种一一映射的关系。程序员可以自己定义该I/O内存资源映射后的虚拟地址。创建好了静态映射表,在内核或驱动中访问该 I/O资源时则无需再进行ioreamp动态映射,可以直接通过映射后的I/O虚拟地址去访问它。

      下面详细分析这种机制的原理并举例说明如何通过这种静态映射的方式访问外设I/O内存资源。

      内核提供了一个重要的结构体structmachine_desc ,这个结构体在内核移植中起到相当重要的作用,内核通过machine_desc结构体来控制系统体系架构相关部分的初始化。

      machine_desc结构体的成员包含了体系架构相关部分的几个最重要的初始化函数,包括map_io,init_irq,init_machine以及phys_io , timer成员等。

      machine_desc结构体定义如下:

      structmachine_desc {

      /*

      * Note! The firstfour elements are used

      * by assemblercode in head-armv.S

      */

      unsignedint       nr;        /* architecturenumber    */

      unsignedint        phys_io;    /*start of physical io    */

      unsignedint        io_pg_offst;    /*byte offset for io

      * page tabeentry    */

      constchar       *name;        /* architecturename    */

      unsignedlong        boot_params;   /* tagged list        */

      unsignedint        video_start;    /*start of video RAM    */

      unsignedint        video_end;    /*end of video RAM    */

      unsignedint        reserve_lp0 :1;   /* never has lp0    */

      unsignedint        reserve_lp1 :1;   /* never has lp1    */

      unsignedint        reserve_lp2 :1;   /* never has lp2    */

      unsignedint        soft_reboot :1;   /* soft reboot        */

      void           (*fixup)(struct machine_desc *,

      struct tag *,char **,

      struct meminfo*);

      void           (*map_io)(void);/* IO mapping function    */

      void           (*init_irq)(void);

      structsys_timer    *timer;       /* system tick timer    */

      void           (*init_machine)(void);

      };

      这里的map_io成员即内核提供给用户的创建外设I/O资源到内核虚拟地址静态映射表的接口函数。Map_io成员函数会在系统初始化过程中被调用,流程如下:

      Start_kernel-> setup_arch() --> paging_init() --> devicemaps_init()中被调用Machine_desc结构体通过MACHINE_START宏来初始化。

      注:MACHINE_START的使用及各个成员函数的调用过程请参考:

      http://blog.chinaunix.net/u2/60011/showart_1010489.html

      用户可以在定义Machine_desc结构体时指定Map_io的接口函数,这里以s3c2410平台为例。

      s3c2410 machine_desc结构体定义如下:

      /*arch/arm/mach-s3c2410/Mach-smdk2410.c*/

      MACHINE_START(SMDK2410,"SMDK2410") /* @TODO: request a new identifier and switch

      * to SMDK2410 */

      /* Maintainer:Jonas Dietsche */

      .phys_io   = S3C2410_PA_UART,

      .io_pg_offst   = (((u32)S3C24XX_VA_UART)>> 18) & 0xfffc,

      .boot_params   = S3C2410_SDRAM_PA + 0x100,

      .map_io       = smdk2410_map_io,

      .init_irq   = s3c24xx_init_irq,

      .init_machine   = smdk2410_init,

      .timer       = &s3c24xx_timer,

      MACHINE_END

      如上,map_io被初始化为smdk2410_map_iosmdk2410_map_io即我们自己定义的创建静态I/O映射表的函数。在Porting内核到新开发板时,这个函数需要我们自己实现。

      (注:这个函数通常情况下可以实现得很简单,只要直接调用iotable_init创建映射表就行了,我们的板子内核就是。不过s3c2410平台这个函数实现得稍微有点复杂,主要是因为它将要创建IO映射表的资源分为了三个部分(smdk2410_iodesc, s3c_iodesc以及s3c2410_iodesc)在不同阶段分别创建。这里我们取其中一个部分进行分析,不影响对整个概念的理解。)

      S3c2410平台的smdk2410_map_io函数最终会调用到s3c2410_map_io函数。

      流程如下:s3c2410_map_io -> s3c24xx_init_io -> s3c2410_map_io

      下面分析一下s3c2410_map_io函数:

      void __init s3c2410_map_io(struct map_desc *mach_desc, intmach_size)

      {

      /* register ourio-tables */

      iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));

      ……

      }

      iotable_init内核提供,定义如下:

      /*

      * Create thearchitecture specific mappings

      */

      void __initiotable_init(struct map_desc *io_desc, int nr)

      {

      int i;

      for (i = 0;i  nr; i++)

      create_mapping(io_desc+ i);

      }

      由上知道,s3c2410_map_io最终调用iotable_init建立映射表。

      iotable_init函数的参数有两个:一个是map_desc类型的结构体,另一个是该结构体的数量nr。这里最关键的就是struct map_descmap_desc结构体定义如下:

      /*include/asm-arm/mach/map.h */

      struct map_desc {

      unsigned longvirtual;    /* 映射后的虚拟地址 */

      unsigned long pfn;       /* I/O资源物理地址所在的页帧号 */

      unsigned longlength;    /* I/O资源长度 */

      unsigned inttype;        /* I/O资源类型 */

      };

      create_mapping函数就是通过map_desc提供的信息创建线性映射表的。

      这样的话我们就知道了创建I/O映射表的大致流程为:只要定义相应I/O资源的map_desc结构体,并将该结构体传给iotable_init函数执行,就可以创建相应的I/O资源到内核虚拟地址空间的映射表了。

      我们来看看s3c2410是怎么定义map_desc结构体的(即上面s3c2410_map_io函数内的s3c2410_iodesc)

      /*arch/arm/mach-s3c2410/s3c2410.c */

      static structmap_desc s3c2410_iodesc[]__initdata = {

      IODESC_ENT(USBHOST),

      IODESC_ENT(CLKPWR),

      IODESC_ENT(LCD),

      IODESC_ENT(TIMER),

      IODESC_ENT(ADC),

      IODESC_ENT(WATCHDOG),

      };

      IODESC_ENT宏如下:

      #defineIODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x,

      __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }

      展开后等价于:

      static structmap_desc s3c2410_iodesc[]__initdata = {

      {

      .virtual   =     (unsigned long)S3C24XX_VA_ LCD),

      .pfn       =     __phys_to_pfn(S3C24XX_PA_ LCD),

      .length   =    S3C24XX_SZ_LCD,

      .type   =     MT_DEVICE

      },

      ……

      };

      S3C24XX_PA_ LCDS3C24XX_VA_ LCD为定义在map.h内的LCD寄存器的物理地址和虚拟地址。在这里map_desc 结构体的virtual成员被初始化为S3C24XX_VA_ LCDpfn成员值通过__phys_to_pfn内核函数计算,只需要传递给它该I/O资源的物理地址就行。Length为映射资源的大小。 MT_DEVICEI/O类型,通常定义为MT_DEVICE

      这里最重要的即virtual 成员的值S3C24XX_VA_LCD,这个值即该I/O资源映射后的内核虚拟地址,创建映射表成功后,便可以在内核或驱动中直接通过该虚拟地址访问这个I/O资源。

      S3C24XX_VA_ LCD以及S3C24XX_PA_ LCD定义如下:

      /*include/asm-arm/arch-s3c2410/map.h*/

      /* LCD controller*/

      #define S3C24XX_VA_LCD         S3C2410_ADDR(0x00600000)  //LCD映射后的虚拟地址

      #define S3C2410_PA_LCD          (0x4D000000)    //LCD寄存器物理地址

      #define S3C24XX_SZ_LCD          SZ_1M       //LCD寄存器大小

      S3C2410_ADDR 定义如下:

      #define S3C2410_ADDR(x)       ((void __iomem *)0xF0000000 + (x))

      这里就是一种线性偏移关系,即s3c2410创建的I/O静态映射表会被映射到0xF0000000之后。(这个线性偏移值可以改,也可以你自己在virtual成员里手动定义一个值,只要不和其他IO资源映射地址冲突,但最好是在0XF0000000之后。)

      (注:其实这里S3C2410_ADDR的线性偏移只是s3c2410平台的一种做法,很多其他arm平台采用了通用的IO_ADDRESS宏来计算物理地址到虚拟地址之前的偏移。

      IO_ADDRESS宏定义如下:

      /*include/asm/arch-versatile/hardware.h */

      /* macro to getat IO space when running virtually */

      #defineIO_ADDRESS(x)           (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) +

      0xf0000000) )

      s3c2410_iodesc这个映射表建立成功后,我们在内核中便可以直接通过S3C24XX_VA_ LCD访问LCD的寄存器资源。

      如:S3c2410 lcd驱动的probe函数内

      /* Stop the videoand unset ENVID if set */

      info->regs.lcdcon1&= ~S3C2410_LCDCON1_ENVID;

      lcdcon1 = readl(S3C2410_LCDCON1); //read映射后的寄存器虚拟地址

      writel(lcdcon1& ~S3C2410_LCDCON1_ENVID,S3C2410_LCDCON1); //write映射后的虚拟地址

      S3C2410_LCDCON1寄存器地址为相对于S3C24XX_VA_LCD偏移的一个地址,定义如下:

      /*include/asm/arch-s3c2410/regs-lcd.h*/

      #define S3C2410_LCDREG(x) ((x) + S3C24XX_VA_LCD)

      /* LCD controlregisters */

      #define S3C2410_LCDCON1       S3C2410_LCDREG(0x00)

      到此,我们知道了通过map_desc结构体创建I/O内存资源静态映射表的原理了。总结一下发现其实过程很简单,一通过定义map_desc结构体创建静态映射表,二在内核中通过创建映射后虚拟地址访问该IO资源。

      三、I/O静态映射方式应用实例

      I/O静态映射方式通常是用在寄存器资源的映射上,这样在编写内核代码或驱动时就不需要再进行ioremap,直接使用映射后的内核虚拟地址访问。同样的IO资源只需要在内核初始化过程中映射一次,以后就可以一直使用。

      寄存器资源映射的例子上面讲原理时已经介绍得很清楚了,这里我举一个SRAM的实例介绍如何应用这种I/O静态映射方式。当然原理和操作过程同寄存器资源是一样的,可以把SRAM看成是大号的I/O寄存器资源。

      比如我的板子在0x30000000位置有一块64KB大小的SRAM。我们现在需要通过静态映射的方式去访问该SRAM。我们要做的事内容包括修改kernel代码,添加SRAM资源相应的map_desc结构,创建sram到内核地址空间的静态映射表。写一个Sram Module,Sram Module 内直接通过静态映射后的内核虚拟地址访问该sram

      第一步:创建SRAM静态映射表

      在我板子的map_des结构体数组(xxx_io_desc)内添加SRAM资源相应的map_desc。如下:

      static structmap_desc xxx_io_desc[] __initdata = {

      …………

      {

      .virtual   = IO_ADDRESS(XXX _UART2_BASE),

      .pfn       = __phys_to_pfn(XXX _UART2_BASE),

      .length       = SZ_4K,

      .type       = MT_DEVICE

      },{

      .virtual   = IO_ADDRESS(XXX_SRAM_BASE),

      .pfn       = __phys_to_pfn(XXX_SRAM_BASE),

      .length       = SZ_4K,

      .type       = MT_DEVICE

      },

      };

      宏XXX_SRAM_BASE为我板子上SRAM的物理地址,定义为0x30000000。我的kernel是通过IO_ADDRESS的方式计算内核虚拟地址的,这点和之前介绍的S3c2410有点不一样。不过原理都是相同的,为一个线性偏移范围在0xF0000000之后。

      第二步:写个SRAM Module,Module中通过映射后的虚拟地址直接访问该SRAM资源

      SRAM Module代码如下:

      /* Sram TestingModule */

      ……

      static voidsram_test(void)

      {

      void * sram_p;

      char str[] ="Hello,sram!\n";

    sram_p = (void *)IO_ADDRESS(XXX_SRAM_BASE); /* 通过IO_ADDRESS宏得到SRAM映射后的虚拟地址 */

      memcpy(sram_p,str, sizeof(str));    // str字符数组拷贝到sram

      printk(sram_p);

      printk("\n");

      }

      static int __initsram_init(void)

      {

      struct resource *ret;

      printk("RequestSRAM mem region ............\n");

      ret =request_mem_region(SRAM_BASE, SRAM_SIZE, "SRAM Region");

      if (ret ==NULL) {

      printk("RequestSRAM mem region failed!\n");

      return -1;

      }

      sram_test();

      return 0;

      }

      static void__exit sram_exit(void)

      {

      release_mem_region(SRAM_BASE,SRAM_SIZE);

      printk("ReleaseSRAM mem region success!\n");

      printk("SRAMis closed\n");

      }

      module_init(sram_init);

      module_exit(sram_exit);

      在开发板上运行结果如下:

      / # insmodbin/sram.ko

      Request SRAM memregion ............

      Hello,sram!     &szlig; 这句即打印的SRAM内的字符串

      / # rmmod sram

      Release SRAM memregion success!

      SRAM is close

      实验发现可以通过映射后的地址正常访问SRAM

      最后,这里举SRAM作为例子的还有一个原因是通过静态映射方式访问SRAM的话,我们可以预先知道SRAM映射后的内核虚拟地址(通过 IOADDRESS计算)。这样的话就可以尝试在SRAM上做点文章。比如写个内存分配的MODULE管理SRAM或者其他方式,将一些critical 的数据放在SRAM内运行,这样可以提高一些复杂程序的运行效率(SRAM速度比SDRAM快多了),比如音视频的编解码过程中用到的较大的buffer 等。

    展开全文
  • 为了保护您的重要信息以免丢失,无论是意外丢失还是恶意盗取,您的安全解决方案必须涵盖可移动存储设备、物理及无线接口和用户。 “SafeGuard外设控管(Configuration Protection) ”可控制并保护每一个接口上的端点...
  • MAX3420E可与任何SPI主控制器相连,以构成全速USB外设器件。尽管一般都由MAX3420来管理底层USB信令,但是需要处理USB事件时,SPI主控制器必须参与处理,当MAX3420的INT引脚指示有中断发生时,SPI主控制器将读取14个...
  • 能不能通过外设的mac地址进行指定连接,可是要获取mac地址,必须要先连接外设呀感觉有点矛盾, 或者全部扫描连接符合mac地址的留下不符合的断开然后停止扫描,是不是效率低?
  • 在之前的一篇文章用devmem2读写设备IO内存中,我介绍了devmem2这个通过读写/dev/mem文件实现从用户空间访问外设寄存器的工具,但是对于PCIE设备,特别是FPGA模拟出来的自定义PCIE设备,该工具在x64平台下可能会发出...

    背景

    在之前的一篇文章用devmem2读写设备IO内存中,我介绍了devmem2这个通过读写/dev/mem文件实现从用户空间访问外设寄存器的工具,但是对于PCIE设备,特别是FPGA模拟出来的自定义PCIE设备,该工具在x64平台下可能会发出64位的内存读写请求,而FPGA模拟的外设寄存器一般都映射到32位地址空间,此时CPU就会因FPGA工作不正常而卡死。
    此时驱动必须用ioread32接口来读写外设寄存器,而该接口无法被用户程序调用,不利于调试,最好有一种既能从用户空间访问,又能避免PCIE发出64位地址访问请求的方法。

    sysfs和PCI的resource属性

    现在较新的内核(4.15+)都支持sysfs,且每个PCIE设备都对应一个目录

    /sys/bus/pci/[domain]:[bus]:[device].[function]/
    

    该目录下有这些属性文件(有删减):

    tree /sys/bus/pci/devices/0000\:01\:00.0/
    /sys/bus/pci/devices/0000:01:00.0/
    ├── class
    ├── config
    ├── device
    ├── dma_mask_bits
    ├── driver -> ../../../../bus/pci/drivers/f260_mainfpga
    ├── enable
    ├── reset
    ├── resource
    ├── resource0   //对应BAR0寄存器空间
    ├── resource1   //对应BAR1寄存器空间
    ├── uevent
    └── vendor
    

    只要将resource0这样的属性文件/dev/mem文件一样mmap到用户进程的虚拟地址空间,就可以像devmem2工具那样通过解引用的方式访问寄存器,而不用ioread32/iowrite32等内核函数。

    pcie寄存器查看工具:pcimem

    有人已经提供了现成的工具pcimem,不过github时常抽风,我转载到了我的gitee以供下载

    用法

    该工具用法跟devmem2很像(因为代码是基于devmem2修改的😂)

    Usage:  ./pcimem { sysfile } { offset } [ type*count [ data ] ]
            sys file: sysfs file for the pci resource to act on
            offset  : offset into pci memory region to act upon
            type    : access operation type : [b]yte, [h]alfword, [w]ord, [d]ouble-word
            *count  : number of items to read:  w*100 will dump 100 words
            data    : data to be written
    

    用法举例

    sudo ./pcimem /sys/bus/pci/devices/0001\:00\:07.0/resource0   0x100    w          0x00
                                                      BAR0      寄存器偏移 访问粒度word  写入0x00(读的话不填该参数)
    

    总结

    个人猜测是resource属性文件的驱动代码实现了普通内存地址到io内存地址的转换。

    展开全文
  • 要对音频外设进行管理,所以我们必须明确当前Andorid系统支持的外设设备有哪些。当前Andorid6.0是通过一个整型变量去针对不同的音频外设进行标志与表示。任何可用的音频外设在这个整型变量中用1个二进制的标志为去...
  • 我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。 Linux内核访问外设I/O内存资源的方式...
  • 我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。 Linux内核访问外设I/O内存资源的方式...
  • 我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。 Linux内核访问外设I/O内存...
  • Linux内核访问外设I/O资源的方式 我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。...
  • CPU是计算机的控制核心它的功能是执行指令完成算数运算逻辑运算并对整机进行控制 存储器用于存储程序和数据 输入/输出接口又称I/O接口是CPU和外设之间相连的逻辑电路外设必须通过接口才能和CPU相连不同的外设所用...
  • 必须使用真机调试</li><li>ios操作系统至少要在6.0以上</li></ul> 情况2:外设没有开启广播 <ul><li>默认情况下打开手机或者ipad的蓝牙,在使用babybluetooth是扫描不到设备的,因为手机和ipad...
  • 一般的外设编程可以通过PB通过的串口编程,也有部分特殊的,可由厂家直接提供技术支持。 各种外设如果接的是COM,必须在打开的时候,让其初始化,一般卡可在刷卡的时候再初始化,刷卡结束后,再把COM口关闭。因为...
  • 默认外设I/O资源不在Linux内核空间中的,如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。Linux内核访问外设I/O方式有两种:动态映射...
  • 我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。 Linux内核访问外设I/O内存资源的方式...
  • 介绍显卡之前,必须得和大家交待清楚,那么多的外部设备,cpu是如何与他们交流。 大家都学过微机接口技术吧?没学过也没关系,反正我也只是笼统地说说^_^,保证大家一定能看得懂。 按理说,如果硬件种类较少,让...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 332
精华内容 132
关键字:

外设必须通过