μClinux嵌入系统外部硬件设备快速调试

摘要:为

了加快开发调试μClinux嵌入式系统的外部硬件设备,采用直接物理地址的设备访问方法,在μClinux嵌入式系统中实现了外部硬件设备的快速访问。

使用地址映像,将设备的寄存器映像到处理器的内存空间统一编址,通过指针定义的地址操作函数对外设备进行访问。该方法可以在μClinux操作系统支持的

嵌入式系统的硬件环境中进行硬件外部设备的快速调试,避免了因等待外部硬件设备驱动程序的编写而耽误外部硬件调试的时间,从而加快外部硬件设备调试速度,

提高硬件开发调试效率。

关键词:方法 μClinux硬件 调试 快速

在传感器网络节点中,采用了基于Linux的嵌入式操作系统。开发基于Linux操作系统

的嵌入式微处理器应用系统,关键是Linux能够访问嵌入式处理器上扩展连接的外部设备。一旦能够访问连接的外部芯片设备,就可以灵活地在Linux上运

行对嵌入式系统外部设备的有关访问控制应用。

Linux在个人PC机上的设备驱动框架作了介绍。介绍了μClinux中访问嵌入式系统

外部设备的设备驱动方式的框架。不过对于设备驱动程序的操作函数的实现由于与具体的外设备硬件有关,没有实现的具体统一方案。设备驱动方式采用通用的文件

访问方式操作设备,这给对硬件底层不了解的高层用户的程序设计带来了方便。但对于硬件的设计和调试人员来说,不了解底层硬件的操作就无法实现设备的访问。

硬件设计人员必须实现访问函数的具体操作过程,以达到对外部扩展设备的访问测试和灵活控制。也就是说,先要完成设备驱动程序,然后才能进行下一步的硬件设

备调试。

编写和实现设备驱动程序必须先了解和实现对设备底层的访问,这是个复杂的过程。先要掌握处

理器如何寻址外部设备、如何配置外部设备;再实现底层的地址访问函数;然后再编写设备驱动程序的实现函数,进而编写设备驱动程序;将驱动程序编译进

Linux操作系统内核;最后在Linux系统中通过标准的设备访问方式访问外部设备。

采用设备驱动方式需要很多时间,以至于耽误硬件设计调试的进程。另一方面,由于应用于嵌入

式的Linux不支持动态的加载设备驱动模块,只能将设备的模块编译进Linux内部,也就是要将设备驱动程序重新编译进用于嵌入式的Linux内核中,

为此采用驱动方式又增加了内核的代码。

在μClinux操作系统中,可以采用直接物理地址访问外部扩展设备,针对设备寄存器的地

址单元进行读写操作,直接与硬件接触,而且便于从最底层了解设备的操作,直接与硬件接触,而且便于从最底层了解设备的工作方式,加快开发调试产品的速度。

该方法仅仅修改少量的代码,采用直接地址的访问方式能够快速完成对外设备的访问测试。与设备驱动方式相比,重新编译后使内核代码增加较少。而在

μClinux中要采用直接物理地址的外部设备访问,需要修改启动代码,建立设备访问函数,需要一定技巧。本文以Motorola的ColdFire

MCF5272嵌入式微处理器平台为例,介绍了μClinux对外部设备的快速访问方法。

1 存储空间编址

对于μClinux来说,其设计是针对没有MMU(Memory Manage

Unit)的处理器,即μClinux不能使用处理器的虚拟内存管理技术,μClinux采用存储器的分页管理,系统在启动时把实际存储器进行分页。在加

载应用程序时程序分页加载。但由于没有MMU管理,实际上μClinux采用实存储器管理策略。

ΜClinux系统对于内存的访问是直接的,它对地址的访问不需要经过MMU,而是直接送到地址线上输出,所有程序中访问的地址都是实际的物理地址。操作系统对内存空间没有保护,各个进程实际上共享一个运行空间。

ΜClinux采用了实内存模式,各个内部段在物理内存(没有虚存)层面都是连续的,其内存空间的地址映像如图1。

根据内存空间是否独立,可以将I/O空间的配置分为两种:一种是I/O空间与内存空间相互

独立,这样I/O空间的访问需要使用专门的I/O函数如inb和outb等。Intel

CPU就使用这种方法。另一种是将I/O寄存器作为内存的一部分,即I/O寄存器与内存统一编址,这样使用普通的内存访问语句即可读写I/O寄存器。

Motorola

68K处理器就采用这种体系结构,处理器MCF5272也统一编址。即其RAM、FLASH和外设I/O均统一编址,没有地址变换和内存保护。

2 快速设备访问

在C语言中,用指针可以对内存地址单元进行直接访问,因此在设计中可以采用指针对外部设备进行快速操作。

2.1 地址映像

为了访问外部设备,首先应将外设的寄存器映像到MCF5272的内存,与内存统一编址。为此,需要修改相应代码。

用于COLDFIRE MCF5272的嵌入式μClinux启动代码由两部分组成:

μClinux/linux/arch/m68knommu/platform/5272/MOTOROLA/crt0_rom.S

μClinux/linux/arch/m68knommu/platform/5272/sysinit.c

其中crt0_rom.S由汇编写成,完成CPU的初始化设置,这是整个软件体系的最开始

执行的代码入口,CPU一加电就跳到这里执行;sysinit.c为C语言代码,完成MCF5272的集成模块SIM(如串口、时钟、通用I/O等)、

SDRAM、FLASH和其它外设接口、片选等的初始化设置。

MCF5272的片选CS0~CS7的寄存器CSBR0~CSBR7和

CSOR0~CSOR7可将外设备寄存器的地址映像到内存储空间,这样可以采用对内存空间的访问来达到访问外部设备。其中寄存器CSBR指明了映像的内存

起始地址、映像的内存容量、总线宽度等;寄存器CSOR用于配置访问控制。片选CS0用于启动存储器ROM(FLASH)。

在C语言文件sysinit.c中修改代码以实现外设的寄存器映像功能。应用片选CS2实现的代码如下:

MCF5272_WR_CS_CSBR2(imm,0xffa00001);/寄存器内存开始地址:0xffa00000

MCF5272_WR_CS_CSOR2(imm,0xfff00014);/片选2

其中imm为无符号字符指针,代表了MCF5272系统集成模块(SIM)中的寄存器地址。

2.2 实现访问函数

通过修改启动代码,将外部设备的寄存器单元映像到内存单元后,就可以使用访问内存的宏和指针快速访问外部设备的寄存器。有两类实现设备快速访问的函数。

2.2.1 使用宏定义

(1)对设备的该函数read_register()实现

#define read_register(IMM,OFFSET,SIZE)Mcf5272iord(IMMP,OFFSET,SIZE)

(2)对设备的写函数write_register()实现

#define write_register(IMM,OFFSET,SIZE,DAT)Mcf5272iowr(IMMP,OFFSET,SIZE,DATA)

其中Mcf5272_iord和Mcf5272_iowr为宏。在sysinit.h中有下列宏定义:

(a)用于计算地址的宏

#define Mcf5272_addr(IMM,OFFSET)((void *)&((unsigned char *)IMMP[OFFSET]))

表示基地址为IMM,偏移地址为OFFSET的内存地址。宏返回物理地址。

(b)访问内存的宏

#define Mcf5272_iord(IMMP,OFFSET,SIZE)

(*(volatile uint ## SIZE *)(Mcf5272_addr)(IMMP,OFFSET)))

#define Mcf5272_iowr(IMMP,OFFSET,SIZE,DATA)

(*(volatile uint ## SIZE *)(Mcf5272_addr(IMMP,OFFSET))=(DATA))

分别表示读内存地址单元内容、将数据DATA写入内存地址单元。地址单元的基地址为IMM,偏移地址为OFFSET。SIZE表示每次读写操作的数据度,取值可为8、16、32,分别表示每次操作8位、16位、32位的总线数据。

2.2.2 采用指针直接定义

(1)对设备的读函数inb()、inw()、inl()实现

#define inb(addr)(*(volatile unsigned chart*)(addr))

#define inw(addr)(*(volatile unsignedshort*)(addr))

#define inl(addr)(*(volatile unsigned long*)(addr))

分别是8位、16位、32位数据总线的读函数。

(2)对设备的写函数outb()、outw()、outl()实现

#define outb(data,addr)((*(volatile unsigned char*)(addr))=(data))

#define outw(data,addr)((*(volatile unsigned short*)(addr))=(data))

#define outl(data,addr)((*(volatile unsigned short*)(addr))=(data))

#define outl(data,addr)((*(volatile unsigned long*)(addr))=(data))

分别是8位、16位、32位数据总线的写函数。

3 应用实验

在笔者的传感器网络节点中(见图2),外部设备芯片采用W99200F,它包含100多个

寄存器。在芯片上电复位后,芯片寄存器的复位初始值在手册中是已知的。根据访问方式,它包含三类寄存器:只读、只写、可读写。W99200F芯片部分寄存

器偏移地址及其复位初始化值如表1所示。

表1 W99200F芯片中部分寄存器及其初始化值

寄存器名

偏移地址

访问方式

数据宽度

复位值

Vint_source

0x0d

只读

8

0x40

Vbv_initial

0x18

读写

8

0x13

Vquality

0x19

读写

8

0x08

Vin_cntl

0x21

读写

8

0x0c

Vsize_h

0x24

读写

8

0x2c

修改启动代码和实现访问函数,其中寄存器CSBR2指明了映像的内存起始地址、映像的内存

容量、总线宽度等。重新编译μClinux内核,并将生成的下载文件烧写到FLASH中,重新上电在内核运行起来后(或者mount上宿主机硬盘手动启动

μClinux内核),通过编制一段C语言的测试程序,调用设备访问函数,即可对外部设备芯片的寄存器进行读写。下面是一段测试程序test.c。

#include

#include "io.h" /包含定义的设备访问函数

int main(void)

{

printf("Vint_source:0x%x",inb(0xffa00000+0x0d));

/读寄存器Vint_source初始值

printf("Vbv_initial:0x%x",inb(0xffa00000+0x18));

/向寄存器Vbv_initial写入值0x7f

outb(ox1f,0xffa00000+0x19));/向寄存器Vquality写入值0x1f

outb(0x7f,0xffa00000+0x21));/向寄存器Vin_cntl写入值0x7f

outb(0x2d,0xffa00000+0x24));/向寄存器Vsize_h写入值0x2d

printf(“Vbv_initial:0x%x”,inb(0xffa00000+0x18));

/读寄存器Vbv_initial的值

printf("Vin_cntl:0x%x"inb(0xffa00000+0x21));

/读寄存器Vin_cntl的值

printf("Vsize_h:0x%x",inb(0xffa00000+0x24));

/读寄存器Vsize_h的值

return;

}

该测试程序先读出外部设备上电的初始值;再对外芯片的可读写寄存器进行写操作,后读出写入

的值。在宿主机Linux系统的minicom调试窗口中mount上宿主机硬盘,运行编译好的test程序,得到该测试程序的输出。读出的初始化值与外

部设备手册上的值完全一样,并且写入外部设备寄存器的值与而后读出的值也完全相同。

通过测试检验说明设备访问函数能够按物理地址访问外部设备。比较设备驱动程序方法,该方法

可以在较短时间正确访问外部设备,这样对硬件调试人员来说节约了时间,可以快速进行硬件的开发调试,而不是等待编写好设备驱动程序后才调试硬件,编写设备

驱动程序可以单独进行。因此,在μClinux嵌入系统中采用本文介绍的方法调试外部设备,具有快速方便的特点,大大加快了在μClinux应用系统中的

设备调试,节约了时间。

Linux嵌入外部程序窗口,μClinux嵌入系统外部硬件设备快速调试||μClinux|相关推荐

  1. Android系统修改硬件设备访问权限

    Android系统修改硬件设备访问权限 在硬件抽象层模块文件(so)文件中,提供的函数调用open函数来打开设备文件,比如/dev/gpio,如果不修改设备文件/dev/gpio的访问权限,那么应用程 ...

  2. win10用什么软件测试硬件,Win10系统下硬件设备检测工具的使用方法

    在win10系统中,自带有硬件设备检测工具,当电脑遇到故障的时候就可以用这个工具来检测并处理,可是许多win10系统用户并不知道要怎么使用硬件设备检测工具,接下来小编就给大家分享一下Win10系统下硬 ...

  3. linux底层硬件需求,Linux系统的硬件设备驱动的底层结构讲解

    什么是驱动?最通俗的解释就是"驱使硬件设备行动" 作用?设备驱动与底层硬件直接打交道,按照硬件设备的具体工作方式读写设备寄存器,完成设备的轮询.中断处理.DMA通信,进行物理内存向 ...

  4. linux修改硬件系统时间,Linux修改日期、时间,系统与硬件时间

    Linux的时间分为两种,硬件时间和系统时间两种: 一.查看与修改系统时间 查看系统时间:date # date Fri Nov 26 15:20:18 CST 1999 用指定的格式显示系统时间:  ...

  5. linux系统时间和硬件时间的修改,Linux修改日期、时间,系统与硬件时间

    Linux的时间分为两种,硬件时间和系统时间两种:html 1.查看与修改系统时间spa 查看系统时间:datehtm # dateget Fri Nov 26 15:20:18 CST 1999同步 ...

  6. 一步一步学linux操作系统: 32 输入与输出系统_ 块设备二_直接 I/O,缓存 I/O 与 块设备数据写入请求

    直接 I/O 与 缓存 I/O 可以参见 https://blog.csdn.net/leacock1991/article/details/108035136 对于 ext4 文件系统,最后调用的是 ...

  7. Linux下 Qt界面程序嵌入另一个Qt界面程序_Qt应用嵌入外部进程窗口

    项目工程的实现,想要使用多个程序进行实现,在里面存在一定的调用的过程:调查的情况如下 Qt界面程序嵌入另一个Qt界面程序[Linux] Qt界面程序嵌入另一个Qt界面程序[Linux]_ptc321的 ...

  8. linux时间管理,时钟中断,系统节拍

    目录 1 时钟中断/系统节拍 1.1 简介 1.2 系统时钟中断需要处理的事情 2 HZ 2.1 简介 2.2 动态调节时钟中断 / CONFIG_NO_HZ / 降低功耗/tickless mode ...

  9. linux 触摸屏在dev的那个目录下,各硬件设备在Linux中的文件名

    原标题:各硬件设备在Linux中的文件名 选择好你的硬件设备以后,接下来得要了解一下各硬件在Linux当中扮演得角色.再次强调一下:"在Linux系统中,每个设备都被当成一个文件来对峙&qu ...

最新文章

  1. 【Java 集合】Java 集合的线程安全性 ( 加锁同步 | java.utils 集合 | 集合属性 | java.util.concurrent 集合 | CopyOnWrite 机制 )
  2. 斐波那契数列(fabnacci)java实现
  3. 圆周率里有每个人的银行卡密码和生日?混知乎的程序员果然都是神一般的存在...
  4. mysql修改数据库级别_设置数据库兼容级别的两种方法
  5. 关于使用public class 和 class声明类的区别
  6. git push失败:ssh:connect to host github.com port 22:Connection timed out
  7. 【iOS】iOS开发之使用Mac自动操作制作@1x@2x@3x图片(切图)
  8. 通过整数索引选择一行熊猫系列/数据框
  9. 强化学习: Q-learning实例python实现
  10. mongodb的基本使用
  11. echarts tooltips数据内容过多超出显示范围
  12. 支付宝小程序卡包开发(流程+详细案例+商户会员卡)
  13. 计算机辅助绘图中测距在哪,cad测距(cad测量距离快捷键)
  14. Pytorch入门笔记(一)
  15. netty之微信-群聊的发起与通知(十八)
  16. 哪些实时翻译的软件好用?分享这三款好用的软件
  17. nomasp 博客导读:Lisp/Emacs、Algorithm、Android
  18. 深度学习第55讲:图像的神经风格迁移
  19. 钢铁是怎样炼成的之彭明盛
  20. 066-PHP通过函数名调用函数

热门文章

  1. 离散扫频 、插值扫频、快速扫频
  2. 工具类库系列(一)-StringTool
  3. Redis 为什么是单线程的
  4. 绕过360安全脚本输入内容存在危险字符,安全起见,已被本站拦截
  5. 云服务器怎样搭建静态网站?
  6. showmoney钱包介绍
  7. 极客天成将参加CNCC2022并做DPU技术分享
  8. 我的物联网项目之 城市合伙人战略
  9. iphone一键转移_苹果手机一键换机,所有的软件和数据都会搬移?
  10. vant 引入其他图标