嵌入式实验报告

北京邮电大学

嵌入式系统开发设计

实验报告

姓名:

学号:

班级:

学院:

嵌入式实验报告

目录

一、实验目的 .......................................................................................................... 3

二、实验设备 .......................................................................................................... 3

三、基础实验(实验一~实验七) ...................................................................... 3

1.实验五 ......................................................................................................... 3

2.实验六 ......................................................................................................... 3

3.实验七 ......................................................................................................... 3

四、基本接口实验 .................................................................................................. 6

1. 实验十二 简单设备驱动程序 .......................................................... 6

2.实验十三 CPU GPIO驱动程序设计 ....................................................... 6

3.实验十四 中断实验 .................................................................................. 8

4.实验十五 数码管显示实验 ..................................................................... 9

5.实验十六 LED点阵驱动程序设计 .......................................................... 14 6. 实验十七 AD驱动实验 ..................................................................... 18

7.实验十八 DA驱动实验 ............................................................................ 21

五、实验中遇到的问题及解决方法 .................................................................... 25

六、实验总结 ........................................................................................................ 25

一、实验目的

通过实验熟悉Linux环境,并掌握一些基本接口驱动的写法和用C语言编写简单的实验程序。学习LINUX开发环境的搭建,通讯配置等。并熟练掌握LINUX驱动程序的编写及开发流程。对嵌入式系统有进一步的了解。

二、实验设备

1.一套PXA270EP嵌入式实验箱。

2. 安装Redhat9的宿主PC机,并且配置好ARM Linux的开发环境。

三、基础实验(实验一~实验七)

实验一~七为基础实验, 目的是为后续实验搭建好软、硬件环境,配置好相关的协议、服务,并通过编写最简单的HelloWorld程序进行测试。由于后面的实验都要依靠前面实验的配置,故只着重叙述实验七的具体实现。

1.实验五

实验五为宿主PC机配置了TFTP服务。TFTP(Trivial File Transfer Protocol)是简单文件传输协议,由于特定开发环境的制约,这一服务是必须的。在配置完成后,每次重启宿主PC机时,都须先输入命令:service xinetd restart,以启动TFTP服务。

2.实验六

实验六为宿主PC机配置了NFS服务。NFS(Network File System)指网络文件系统,它实现了文件在不同的系统间使用。当我们想用远端档案时,只需调用“mount”就可以远端系统挂接在自己的档案系统之下。每次重启宿主PC机时,都须先输入命令:service nfs restart,以启动nfs服务。

3.实验七

实验七通过用c语言编写的简单程序HelloWorld,测试前面几个实验是否成功配置好环境,从超级终端可以看到HelloWorld程序的运行结果。

实验步骤:

1) 硬件连接:连接宿主 PC 机和一台 PXA270-RP目标板。

2)打开宿主PC 机电源,进入 Linux操作系统。

3)启动RedHat 9.0 的图形界面,若您是以 root 身份登陆在文本模式下,则输入命令 startx 启动图形界面。进入 RedHat 9.0 图形界面后,打开一个终端窗(Terminal),点击【红帽/System Tools/Terminal】启动终端窗口。

4) 打开计算机超级终端。

5)打开PXA270-EP实验箱电源(或按实验箱上的RESET键),在Windows超级终端中应

该会出现如下图:

6) 在Terminal终端窗口内,输入下列4条命令:

ifconfig eth0 192.168.100 up

service xinetd restart

service nfs restart

service nfs restart

7)在Windows超级终端窗口中,如图,输入下列四条命令:

root

ifconfig eth 192.168.0.50 up

mount -o nolock 192.168.0.100:/ /mnt

cd /mnt

此时,先将该窗口最小化,在后面的第 10 操作步骤中还将会回到该窗口中进行操作。

8)宿主机上打开一个终端窗口(Terminal),输入下列 4 条命令:

cd /home

mkdir HW

cd HW

vi HelloWorld.c /*请您输入程序 7.1 程序清单*/

此时会显示一个空白的屏幕,这条命令的含义是,使用 Vi 编辑器,对一个名叫 HelloWorld.c的文件进行编辑,我们看到的空白窗口是对文件进行编辑的窗口,如下图。就像在Windows系统下面使用写字板等一样道理。

在 vi 里面先单击键盘 A 键,然后左下角会变成—INSER

嵌入式实验报告

嵌入式实验报告

嵌入式实验报告

。输入程序的时候和其他编辑

器是一样的,如下图。

当输入程序完毕后,单击键盘 Esc 键,然后按“:”(冒号)此时左下角会出现冒号然后输入“wq”最后按“Enter”确认存盘退出vi编辑器,如下图。

9)在上面同一个终端窗口中,输入下列 2 条命令交叉编译 HelloWorld.c源程序,并查看生成的.o 目标文件,如图:

arm-linux-gcc –o HelloWorld HelloWorld.c

ls

等到再次出现提示符,代表程序已经正确编译。如果此步出现错误信息,请查看错误信息,并且重新编辑原来的 C文件,修改错误。直到正确编译。

10)重新进入超级终端窗口,即到 PXA270-RP 目标板的 mnt目录下,请您输入下列 3 条命令,运行 HelloWorld 编译成功的 HelloWorld 目标程序:

cd home/HW

ls

嵌入式实验报告

嵌入式实验报告

嵌入式实验报告

./HelloWorld

四、基本接口实验

在完成了基本实验后,我们开始着手基本接口实验。在这些实验中,我们学习如何编写设备驱动程序,及如何用测试程序检验驱动程序是否正确,并通过改写测试程序正常地对驱动程序进行相关操作。

1. 实验十二 简单设备驱动程序

本次实验的任务是编写一个字符型设备驱动程序,并学习在应用程序中调用驱动。考虑到我们初次接触驱动程序的编写,对此还十分陌生,因此指导书中提供了本次实验所要用到的程序源代码。虽然这样一个字符型设备驱动程序并没有任何实际作用,但是它让我们轻松掌握了嵌入式驱动的编写过程,因为复杂繁琐的驱动,其骨架都是相同的。因此,看懂本实验的源代码,学习并模仿其编写方法,对于后续实验有着非常重要的意义。

2.实验十三 CPU GPIO驱动程序设计

在本实验中,我们要编写第一个针对实际硬件的驱动程序。我们知道,凡是操作系统控制外部设备,即使是最简单的硬件电路,也是需要驱动的。本实验涉及的外部硬件只有电阻和发光二极管。我们使用自己编写的驱动程序与应用程序控制GPIO96的电平,通过 LED 的亮灭来判断,是否CPU做出了正确的响应。

补充代码(1)

// ------------------- WRITE -----------------------

ssize_t SIMPLE_GPIO_LED_write (struct file * file ,const char * buf, size_t count, loff_t * f_ops) {

#ifdef OURS_GPIO_LED_DEBUG

printk ("SIMPLE_GPIO_LED_write [ --kernel--]\n");

#endif return count;

}

补充代码(2)

// ------------------- OPEN ------------------------

ssize_t SIMPLE_GPIO_LED_open (struct inode * inode ,struct file * file)

嵌入式实验报告

{

#ifdef OURS_GPIO_LED_DEBUG

printk ("SIMPLE_GPIO_LED_open [ --kernel--]\n");

#endif

MOD_INC_USE_COUNT; return 0;

}

补充代码(3)

// -------------------------------------------------

struct file_operations GPIO_LED_ctl_ops ={

open:SIMPLE_GPIO_LED_open,

read:SIMPLE_GPIO_LED_read,

write:SIMPLE_GPIO_LED_write,

ioctl:SIMPLE_GPIO_LED_ioctl,

release:SIMPLE_GPIO_LED_release,

};

作业代码:

要求:编写一个程序,使得目标板的核心板上的LED闪烁产生亮7秒,灭2秒的效果。

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <fcntl.h>

#include <unistd.h>

#define DEVICE_NAME “/dev/gpio_led_ctl”

#define LED_ON 0

#define LED_OFF 1

//-----------------------main----------------------------------

int main(void)

{

int fd;

int ret;

char *i;

printf(“\nstart gpio_led_driver test\n\n”);

fd = open(DEVICE_NAME,O_RDWR);

printf(“fd = %d\n”,fd);

if (fd == -1)

{

printf("open device %s error\n",DEVICE_NAME);

}

else

{

while(1)

{ ioctl(fd,LED_OFF);

sleep(2);

ioctl(fd,LED_ON);

sleep(7);

}

ret = close(fd);

printf ("ret=%d\n",ret);

printf ("close gpio_led_driver test\n");

}

return 0;

}// end main

提示:改变代码中数字,可以改变灯亮和熄灭的时间比

3.实验十四 中断实验

在理论课中,我们学习了许多中断方面的知识,包括中断向量、中断优先级、中断过程等。在PXA270系统里,中断控制器分外部设备和 PXA270X 处理器设备产生的两个层次的中断,前者是初级的中断源,后者是次级中断源,大量的次级中断源通常被映射为一个初级中断源。

补充代码(1)

void showversion(void)

{

printk("*********************************************\n");

printk("\t %s \t\n", VERSION);

printk("*********************************************\n\n");

}

static int SimpleINT_temp_count = 0;

补充代码(2)

// ------------------- READ ------------------------

ssize_t SIMPLE_INT_read (struct file * file ,char * buf, size_t count, loff_t * f_ops)

{

#ifdef OURS_INT_DEBUG

printk ("SIMPLE_INT_read [ --kernel--]\n");

#endif

return count;

}

补充代码(3)

// ------------------- WRITE -----------------------

ssize_t SIMPLE_INT_write (struct file * file ,const char * buf, size_t count, loff_t * f_ops) {

#ifdef OURS_INT_DEBUG

printk ("SIMPL_INT_write [ --kernel--]\n");

#endif

return count;

}

补充代码(4)

// -------------------------------------------------

struct file_operations INT_ctl_ops ={

open: SIMPLE_INT_open,

read: SIMPLE_INT_read,

write:SIMPLE_INT_write,

ioctl:SIMPLE_INT_ioctl,

release:SIMPLE_INT_release,

};

通过此实验,我了解了硬件中断管脚与中断号的对应关系,以及中断号与中断处理程序的对应关系,对于今后编写更为复杂的中断程序打下基础。

4.实验十五 数码管显示实验

在此实验中,我们要编写针对74LV164 的驱动程序,并用其串并转换功能来控制八段LED数码管的显示。

补充代码(1)

void showversion(void)

{

printk("*********************************************\n");

printk("\t %s \t\n", VERSION);

printk("*********************************************\n\n");

}

补充代码(2)

// ------------------- READ ------------------------

ssize_t SERIAL_LED_read (struct file * file ,char * buf, size_t count, loff_t * f_ops) {

#ifdef OURS_HELLO_DEBUG

printk ("SERIAL_LED_read [ --kernel--]\n");

#endif

return count;

}

补充代码(3)

// ------------------- WRITE -----------------------

ssize_t SERIAL_LED_write (struct file * file ,const char * buf, size_t count, loff_t * f_ops) {

#ifdef OURS_HELLO_DEBUG

printk ("SERIAL_LED_write [ --kernel--]\n");

#endif

write_byte(* buf);

return count;

}

补充代码(4)

// ------------------- IOCTL -----------------------

ssize_t SERIAL_LED_ioctl (struct inode * inode ,struct file * file, unsigned int cmd, long data) {

#ifdef OURS_HELLO_DEBUG

printk ("SERIAL_LED_ioctl [ --kernel--]\n");

#endif

return 0;

}

补充代码(5)

// ------------------- OPEN ------------------------

ssize_t SERIAL_LED_open (struct inode * inode ,struct file * file)

{

#ifdef OURS_HELLO_DEBUG

printk ("SERIAL_LED_open [ --kernel--]\n");

#endif

MOD_INC_USE_COUNT;

return 0;

}

补充代码(6)

// ------------------- RELEASE/CLOSE ---------------

ssize_t SERIAL_LED_release (struct inode * inode ,struct file * file)

{

#ifdef OURS_HELLO_DEBUG

printk ("SERIAL_LED_release [ --kernel--]\n");

#endif

MOD_DEC_USE_COUNT;

return 0;

}

补充代码(7)

// -------------------------------------------------

struct file_operations SERIAL_LED_ops ={

open: SERIAL_LED_open,

read: SERIAL_LED_read,

write:SERIAL_LED_write,

ioctl:SERIAL_LED_ioctl,

release:SERIAL_LED_release,

};

补充代码(8)

static int __init HW_SERIAL_LED_init(void)

{

int ret = -ENODEV;

ret = devfs_register_chrdev(SERIAL_LED_MAJOR, "serial_led_ctl", &SERIAL_LED_ops); showversion();

if( ret < 0 )

{

printk (" pxa270 init_module failed with %d\n [ --kernel--]", ret); return ret;

}

else

{

printk(" pxa270 serial_led_driver register success!!! [ --kernel--]\n"); }

return ret;

}

补充代码(9)

static int __init pxa270_SERIAL_LED_init(void)

{

int ret = -ENODEV;

#ifdef OURS_HELLO_DEBUG

printk ("pxa270_SERIAL_LED_init [ --kernel--]\n");

#endif

ret = HW_SERIAL_LED_init();

if (ret)

return ret;

return 0;

}

补充代码(10)

static void __exit cleanup_SERIAL_LED(void)

{

#ifdef OURS_HELLO_DEBUG

printk ("cleanup_SERIAL_LED [ --kernel--]\n");

#endif

devfs_unregister_chrdev (SERIAL_LED_MAJOR, "serial_led" );

}

补充代码(11)

MODULE_DESCRIPTION("serial_led driver module");

MODULE_AUTHOR("liduo");

MODULE_LICENSE("GPL");

module_init(pxa270_SERIAL_LED_init);

module_exit(cleanup_SERIAL_LED);

使用测试程序看到的测试结果是数码管按0-9显示输出。

实验作业:

1、实现目标板上的LED数码管循环显示数字9-0。

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <fcntl.h>

#include <unistd.h>

#define DEVICE_NAME "/dev/serial_led"

//--------------------------main----------------------------------

int main(void)

{

int fd;

int ret;

int i,count;

int buf[10] = { 0x6f,0x7f,0x07,0x7d,0x6d,0x66,0x4f,0x5b,0x06,0x3f}; // 9 8 7 6 5 4 3 2 1 0

int data[10];

printf("\nstart serial_led driver test\n\n");

fd = open(DEVICE_NAME, O_RDWR);

printf("fd = %d\n",fd);

if (fd == -1)

{

printf("open device %s error\n",DEVICE_NAME);

}

else

{

while(1)

{

for(count=0;count<10;count++)

{

data[0] = buf[count];

ret=write(fd,data,1);

sleep(1);

}

}

}

ret = close(fd);

printf ("ret=%d\n",ret);

printf ("close serial_led driver test\n");

return 0;

}// end main

提示:buf[10]定义顺序和书上程序相反,实现反向循环显示。

结果显示

嵌入式实验报告

嵌入式实验报告

2、实现目标板上的LED数码管循环显示数字2、4、6、8、0或者8、6、4、2、0。 #include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <fcntl.h> // open() close()

#include <unistd.h> // read() write()

#define DEVICE_NAME "/dev/serial_led"

//----------------------------main------------------------------ int main(void)

{

int fd;

int ret;

int i,count;

int buf[5] = {0x5b, 0x66, 0x7d, 0x7f,0x3f};

// 2 4 6 8 0

int data[5];

printf("\nstart serial_led driver test\n\n");

fd = open(DEVICE_NAME, O_RDWR);

printf("fd = %d\n",fd);

if (fd == -1)

{

printf("open device %s error\n",DEVICE_NAME);

}

else

{

while(1)

{

for(count=0;count<5;count++) {

data[0] = buf[count];

ret=write(fd,data,1);

sleep(1);

}

}

}

ret = close(fd);

printf ("ret=%d\n",ret);

printf ("close serial_led driver test\n");

return 0;

}// end main

提示:buf[5],修改长度,使五个数字循环显示

嵌入式实验报告

结果显示

提示:通过更改显数的顺序,很容易实现实验作业里要求的功能。

5.实验十六 LED点阵驱动程序设计

通过本实验的操作,我们将 8X8 的点阵 LED 驱动起来并通过编写测试程序,使其能够按照您的意图进行显示。要求您还编写更多的测试程序

补充代码(1)

void showversion(void)

{

printk("*********************************************\n");

printk("\t %s \t\n", VERSION);

printk("*********************************************\n\n"); }

补充代码(2)

// ------------------- READ ------------------------

ssize_t SIMPLE_LED_read (struct file * file ,char * buf, size_t count, loff_t * f_ops) {

#ifdef OURS_LED_DEBUG

printk ("SIMPLE_LED_read [ --kernel--]\n");

#endif

return count;

}

补充代码(3)

// ------------------- IOCTL -----------------------

ssize_t SIMPLE_LED_ioctl (struct inode * inode ,struct file * file, unsigned int cmd, long data) {

#ifdef OURS_LED_DEBUG

printk ("SIMPLE_LED_ioctl [ --kernel--]\n");

#endif

嵌入式实验报告

嵌入式实验报告

return 0;

}

补充代码(4)

// -------------------------------------------------

struct file_operations LED_ctl_ops ={

open: SIMPLE_LED_open,

read: SIMPLE_LED_read,

write: SIMPLE_LED_write,

ioctl: SIMPLE_LED_ioctl,

release:SIMPLE_LED_release,

};

补充代码(5)

static int __init pxa270_LED_CTL_init(void)

{

int ret = -ENODEV;

#ifdef OURS_LED_DEBUG

printk ("pxa270_LED_CTL_init [ --kernel--]\n");

#endif

ret = HW_LED_CTL_init();

if (ret)

return ret;

return 0;

}

补充代码(6)

static void __exit cleanup_LED_ctl(void)

{

#ifdef OURS_LED_DEBUG

printk ("cleanup_LED_ctl [ --kernel--]\n");

#endif

outw(0x0000,ioremap_addr);

devfs_unregister_chrdev (SIMPLE_LED_MAJOR, "led_ary_ctl" ); }

作业代码:

1、按横方向隔行扫描led点阵数码管。

int main(void)

{

int fd;

int ret;

unsigned char buf[2] ;

unsigned char c,r;

int i,j;

// begin of led ary

c = 1;

r = 1;

printf("\nstart led_driver test\n\n");

fd = open(DEVICE_NAME, O_RDWR);

printf("fd = %d\n",fd);

if (fd == -1)

{

printf("open device %s error\n",DEVICE_NAME);

}

else {

for (i=1;i<=8;i++) {

buf[0]=c;

buf[1]=~r; // row

for (j=1;j<=8;j++) {

write(fd,buf,2);

printf ("buf[0],buf[1]: [%x,%x]\n",buf[0],buf[1]); usleep(200000); // sleep 0.2 second

c = c<<1;

buf[0]=c; // column

}

c = 1;

r = r<<2; /此处修改/

}

// close

ret = close(fd);

printf ("ret=%d\n",ret);

printf ("close led_driver test\n");

}

return 0;

}// end main

提示:计数每次跳两个格

结果显示

嵌入式实验报告

2、按竖方向顺序扫描led点阵数码管。

代码:

int main(void)

{

int fd;

int ret;

unsigned char buf[2] ;

unsigned char c,r;

int i,j;

// begin of led ary

c = 1;

r = 1;

printf("\nstart led_driver test\n\n");

fd = open(DEVICE_NAME, O_RDWR);

printf("fd = %d\n",fd);

if (fd == -1)

{

printf("open device %s error\n",DEVICE_NAME);

}

else {

for (i=1;i<=8;i++) {

buf[0]=c;

buf[1]=~r; // row

for (j=1;j<=8;j++) {

write(fd,buf,2);

printf ("buf[0],buf[1]: [%x,%x]\n",buf[0],buf[1]); usleep(200000); // sleep 0.2 second

r = r<<1;

buf[1]=~r; // column

}

r = 1;

c = c<<1;

}

// close

ret = close(fd);

printf ("ret=%d\n",ret);

printf ("close led_driver test\n");

}

return 0;

}// end main

提示:改横向为竖向

6. 实验十七 AD驱动实验

通过本实验的操作,我们将 AD 转换器驱动起来并通过编写测试程序,使其能够将模拟信 号量按照我们的要求转换成数字信号量。为了更加清楚地理解 AD 转换器的工作过程,请您再 编写一个测试程序,将 UCB_ADC_INP_AD0 换成其他通道,来观察其他 AD 通道情况。

补充代码(1)

void showversion(void)

{

printk(“*****************************************\n”);

printk(“\t %s \t\n”,VERSION);

printk(“************************************************\n\n”);

}

struct ucb1x00 *ad_ucb;

补充代码(2)

// ------------------- READ ------------------------

static ssize_t adctl_read (struct file * file ,char *buf, size_t count, loff_t *offset)

{

#ifdef OURS_HELLO_DEBUG

printk(“SIMPLE_HELLO_read [--kernel--]\n”);

#endif

return count;

}

补充代码(3)

// ------------------- WRITE -----------------------

ssize_t adctl_write (struct file * file ,const char *buf, size_t count, loff_t *offset)

嵌入式实验报告

{

#ifdef OURS_HELLO_DEBUG

printk(“SIMPLE_HELLO_write [--kernel--]\n”); #endif

return count;

}

补充代码(4)

// ------------------- OPEN ------------------------

ssize_t adctl_open (struct inode * inode ,struct file * file) {

#ifdef OURS_HELLO_DEBUG

printk(“SIMPLE_HELLO_open [--kernel--]\n”); #endif

MOD_INC_USE_COUNT;

return 0;

}

补充代码(5)

// ------------------- RELEASE/CLOSE ---------------

ssize_t adctl_release (struct inode * inode ,struct file * file) {

#ifdef OURS_HELLO_DEBUG

printk(“SIMPLE_HELLO_release [--kernel--]\n”); #endif

MOD_DEC_USE_COUNT;

return 0;

}

补充代码(6)

static struct file_operations adctl_ops = {

read: adctl_read,

write: adctl_write,

ioctl: adctl_ioctl,

open: adctl_open,

release:adctl_release,

};

补充代码(7)

// ------------------- INIT ------------------------

static int __init HW_AD_CTL_init(void)

{

ad_ucb = ucb1x00_get();

int ret = -ENODEV;

ret = devfs_register_chrdev(ADCTL_MAJOR, “ad_ctl”, &adctl_ops);

showversion();

if(ret<0)

{

printk(“pxa270 init_module failed with %d\n [--kernel--]”,ret);

return ret;

}

else

{

printk(“pxa270 serial_led_driver register success!!! [--kernel--]\n”); }

adctl_dev_handle = devfs_register( NULL, "ad_ctl", DEVFS_FL_DEFAULT,ADCTL_MAJOR, 0, S_IFCHR, &adctl_ops, NULL);

return ret;

}

补充代码(8)

static int __init pxa270_AD_CTL_init(void)

{

int ret = -ENODEV;

#ifdef OURS_HELLO_DEBUG

printk(“pxa270_AD_CTL_init [--kernel--]\n”);

#endif

ret = HW_AD_CTL_init();

if(ret)

return ret;

return 0;

}

补充代码(9)

static void __exit cleanup_AD_ctl(void)

{

#ifdef OURS_HELLO_DEBUG

printk(“cleanup_AD_ctl [--kernel--]\n”);

#endif

devfs_unregister_chrdev(ADCTL_MAJOR, “ad_ctl”);

devfs_unregister(adctl_dev_handle);

}

作业代码:

要求:将UCB_ADC_INP_AD0换为其他通道并观察。

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <fcntl.h> // open() close()

#include <unistd.h> // read() write()

#define DEVICE_NAME "/dev/ad_ctl"

#define UCB_ADC_INP_AD0 (4 << 2)

#define UCB_ADC_INP_AD1 (5 << 2)

#define UCB_ADC_INP_AD2 (6 << 2)

#define UCB_ADC_INP_AD3 (7 << 2)

//--------------------------- main ------------------------------- int main(void)

{

int fd;

int ret;

int val0,val1;

char *i;

printf("\nstart ad_ctl test\n\n");

fd = open(DEVICE_NAME, O_RDWR);

printf("fd = %d\n",fd);

if (fd == -1)

{

printf("open device %s error\n",DEVICE_NAME);

}

else

{

ioctl(fd);

for(i=0;i<50;i++)

{

Val0 = ioctl(fd,UCB_ADC_INP_AD1,0);

usleep(100);

val1 = ioctl(fd,UCB_ADC_INP_AD0,0);

printf(“val0 = %d\tval1 = %d\n”,val0,val1;

usleep(500000);

}

ret = close(fd);

printf ("close hello_driver test\n");

}

return 0;

}// end main

提示:交换AD1和AD0

7.实验十八 DA驱动实验

通过本实验的操作,我们使用示波器看到了通过 DA 转换而输出的波形。在此基础上,要求试写一个实现输出三角波的测试程序。

补充代码(1)

#include <linux/config.h>

#include <linux/kernel.h>

#include <linux/sched.h>

#include <linux/timer.h>

#include <linux/init.h>

#include <linux/module.h>

#include <asm/hardware.h>

#include<asm/io.h>

补充代码(2)

void showversion(void)

{

printk("*****************************\n");

printk("\t %s\t \n",VERSION);

printk("*****************************\n");

}

static long ioremap_addr;

补充代码(3)

// ------------------- READ ------------------------

ssize_t SIMPLE_DA_read (struct file * file ,char * buf, size_t count, loff_t * f_ops) {

#ifdef OURS_DA_DEBUG

printk("SIMPLE_DA_read[--kernel--]\n");

#endif

return count;

}

补充代码(4)

// ------------------- WRITE -----------------------

ssize_t SIMPLE_DA_write (struct file * file ,const char * buf, size_t count, loff_t * f_ops) {

#ifdef OURS_DA_DEBUG

printk("SIMPLE_DA_write[--kernel--]\n");

#endif

outb(buf[0],ioremap_addr);

return count;

}

补充代码(5)

// ------------------- IOCTL -----------------------

ssize_t SIMPLE_DA_ioctl (struct inode * inode ,struct file * file, unsigned int cmd, long data) {

#ifdef OURS_DA_DEBUG

printk("SIMPLE_DA_ioctl[--kernel--]\n");

#endif

return 0;

}

补充代码(6)

// ------------------- OPEN ------------------------

ssize_t SIMPLE_DA_open (struct inode * inode ,struct file * file)

{

#ifdef OURS_DA_DEBUG

printk ("SIMPLE_DA_open [ --kernel--]\n");

#endif

MOD_INC_USE_COUNT;

return 0;

}

补充代码(7)

/ -------------------------------------------------

struct file_operations DA_ctl_ops ={

read: SIMPLE_DA_read,

write: SIMPLE_DA_write,

ioctl: SIMPLE_DA_ioctl,

release: SIMPLE_DA_release,

};

补充代码(8)

// ------------------- INIT ------------------------

static int __init HW_DA_CTL_init(void)

{

int ret = -ENODEV;

ret = devfs_register_chrdev(SIMPLE_DA_MAJOR, "da_ctl", &DA_ctl_ops); showversion();

if( ret < 0 )

{

printk (" pxa270: init_module failed with %d\n [ --kernel--]", ret); return ret;

}

else

{

printk(" pxa270 led_driver register success!!! [ --kernel--]\n"); }

}

补充代码(9)

static int __init pxa270_DA_CTL_init(void)

{

int ret = -ENODEV;

#ifdef OURS_DA_DEBUG

printk ("pxa270_DA_CTL_init [ --kernel--]\n");

#endif

ret = HW_DA_CTL_init();

if (ret)

return ret;

return 0;

}

补充代码(10)

static void __exit cleanup_DA_ctl(void)

{

#ifdef OURS_DA_DEBUG

printk ("cleanup_DA_ctl [ --kernel--]\n");

#endif

}

补充代码(11)

MODULE_DESCRIPTION("DA_ctl driver module");

MODULE_AUTHOR("liduo");

MODULE_LICENSE("GPL");

module_init(pxa270_DA_CTL_init);

module_exit(cleanup_DA_ctl);

作业代码:

要求:输出三角波。

//---------------------print--------------------

void da_create_sin(int fd)

{

unsigned char buf[(int)POINT];

unsigned char*c;

unsigned long I;

int j;

double x;

for (j=0;j<POINT;j++) {

if(j<POINT/2)

x=(j/POINT);

else

x=(1-j/POINT);

#ifdef OURS_DEBUG

printf(“%f\t”,x);

#endif

buf[j] = (unsigned char)255*(x/2+1)/2; #ifdef OURS_DEBUG

printf(“%x\n”, buf[j]);

#endif

}

printf(“create sin wave\n”);

printf(“Use\”Ctrl + c\“quit the function\n”); while (1) {

c = buf;

for(j=0;j<POINT;j++) {

write(fd,c,1);

c++;

usleep(1);

}

}

}

提示:修改处改变了发生函数,使原本产生sin函数改为产生三角波函数。测试时选择sin,就会发生三角波。

五、实验中遇到的问题及解决方法

每一次上课重新启动后,当需要将宿主PC机的根目录挂在到PXA270-EP目标板的mnt目录下(即在超级终端中输入命令“mount -o soft,timeo=100,rsize=1024 192.168.0.100:/ /mnt”)时,常显示无法挂载。

解决方法:在超级终端下的挂载命令应该用“mount –o nolock 192.168.0.100:/ /mnt”,如果依然不能挂载需要重启NFS服务,即在PC机终端中输入命令“service nfs restart”两遍后就可以挂载,当然有时候也可能是因为网线没插好。

在每次重启机器之后都需要将PC机终端的IP地址和开发板中的系统的IP地址设定正确,不然也无法挂载。

六、实验总结

本学期的所有实验均在宿主PC机与PXA270-EP目标板上进行。在实验中,我们先建立硬件实验平台,又建立主机软件开发环境,接着为实验进行各项配置,最后完成了各个实验中的多种功能。值得注意的是,前期的硬件、软件准备必须完整无误地实现,后续的实验才能顺利进行。所以,打基础的工作一定要仔细谨慎。后续实验中虽然给出了驱动程序的框架,仍需要我们自己补充完整,并开动脑筋举一反三,在原代码的基础上进行一定修改以实现新的功能。

通过这学期的实验,我逐步完成了建立实验软件开发平台,搭建实验编译软件环境,在PC上编辑、编译一个应用程序,并且在嵌入式系统上运行和调试它的过程。在实验中,不难发现,编译驱动程序大体框架都是一样的,比如里面的读函数、写函数、ioctl函数、打开、关闭以及函数模块的初始化并且在超级终端上显示出等。但所不同的是,要根据不同的实验要求修改名称,并且对其中必要的部分进行修改。

除此之外,我认为很多基础知识对实验的进行也起着非常大的作用,例如数码管的显示原理。在掌握了基础知识之后,上机的过程会显得相对简单,尤其是代码框架已经给出,我们所以需要做的就是根据需要稍作改动来得到我们想要的结果。

在实验过程中常常会遇到各种各样的问题,刚开始时我不知如何是好,只能求助于老师和同学,后来随着实验的进行,我对实验的内容和虚拟机都有了一定的了解,遇到问题时也可以静下心来思考其原因,自己尝试各种方法去解决问题。在实验中,我了解了一套完整的嵌入式系统驱动程序开发的全过程,学到的内容非常丰富,相信在学习了这些内容后,在今后的学习工作中接触到类似内容,我不会感到无从下手,而是能够有条不紊。

相关推荐