北京邮电大学
嵌入式系统开发设计
实验报告
姓名:
学号:
班级:
学院:
目录
一、实验目的 .......................................................................................................... 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函数、打开、关闭以及函数模块的初始化并且在超级终端上显示出等。但所不同的是,要根据不同的实验要求修改名称,并且对其中必要的部分进行修改。
除此之外,我认为很多基础知识对实验的进行也起着非常大的作用,例如数码管的显示原理。在掌握了基础知识之后,上机的过程会显得相对简单,尤其是代码框架已经给出,我们所以需要做的就是根据需要稍作改动来得到我们想要的结果。
在实验过程中常常会遇到各种各样的问题,刚开始时我不知如何是好,只能求助于老师和同学,后来随着实验的进行,我对实验的内容和虚拟机都有了一定的了解,遇到问题时也可以静下心来思考其原因,自己尝试各种方法去解决问题。在实验中,我了解了一套完整的嵌入式系统驱动程序开发的全过程,学到的内容非常丰富,相信在学习了这些内容后,在今后的学习工作中接触到类似内容,我不会感到无从下手,而是能够有条不紊。
武汉大学计算机学院08级嵌入式系统设计实验报告班级08级计科5班指导老师武小平学期20xx20xx第1学期小组成员目录一设计题目选…
嵌入式系统实验报告姓名:##学号:##班级:计算机科学与技术非师范121班实验一LCD控制一、实验目的1、初步掌握液晶显示屏的使用…
嵌入式实验报告姓名邓庆学号1075490019学院通信工程学院实验一电源复位时钟管理单元一实验目的1了解如何配置不同的时钟2如何使…
嵌入式系统实验报告学院测量与通信工程学院专业信号与信息处理学生姓名姜元学号1320xx0050指导教师董静薇一实验目的了解Boot…
嵌入式系统实验报告小组成员指导老师实验三键盘及LED驱动实验一实验目的1学习键盘及LED驱动原理2掌握ZLG7289芯片的使用方法…
重庆航天职业技术学院课程作业课程名称嵌入式系统专选班级学号姓名成绩前言嵌入式系统是基于单片机的一种升级版它是以应用为中心以计算机技…
嵌入式系统设计实验报告班级学号姓名成绩指导教师1实验一11实验名称博创UP3000实验台基本结构及使用方法12实验目的1学习嵌入式…
大连理工大学本科实验报告课程名称嵌入式系统实验学院系电子信息与电气工程学部专业自动化班级学号学生姓名20xx年月大连理工大学实验报…
实验报告20xx20xx学年第二学期课程名称ARM嵌入式系统原理与开发实验名称嵌入式Linux交叉开发环境建立与程序开发实验时间指…
ARM嵌入式系统基础综合实验报告姓名班级学号指导教师实验时间20xx年11月24日目录一实验目的3二实验设备3三实验内容3四实验预…
《嵌入式系统》实验报告姓名:学号:班级:湖南工业大学电气与信息工程学院20xx年x月实验一ARM汇编指令实验1一、实验目的1.初步…