电脑桌面
添加蜗牛文库到电脑桌面
安装后可以在桌面快捷访问

北邮电子院专业实验报告

栏目:合同范文发布:2025-01-28浏览:1收藏

北邮电子院专业实验报告

第一篇:北邮电子院专业实验报告

电子工程学院

ASIC专业实验报告

班级: 姓名:

学号: 班内序号:

第一部分 语言级仿真

LAB 1:简单的组合逻辑设计一、二、实验目的 实验原理 掌握基本组合逻辑电路的实现方法。

本实验中描述的是一个可综合的二选一开关,它的功能是当sel = 0时,给出out = a,否则给出结果out = b。在Verilog HDL中,描述组合逻辑时常使用assign结构。equal=(a==b)?1:0是一种在组合逻辑实现分支判断时常用的格式。parameter定义的size参数决定位宽。测试模块用于检测模块设计的是否正确,它给出模块的输入信号,观察模块的内部信号和输出信号。

三、源代码

mux.v module scale_mux(out,sel,b,a);parameter size=1;output[size-1:0] out;input[size-1:0]b,a;input sel;assign out =(!sel)?a:

(sel)?b:

{size{1'bx}};endmodule

mux_test.v `define width 8 `timescale 1 ns/1 ns module mux_test;

reg[`width:1]a,b;

wire[`width:1]out;

reg sel;

scale_mux#(`width)m1(.out(out),.sel(sel),.b(b),.a(a));

initial

begin

$monitor($stime,“sel=%b a=%b b=%b out=%b”,sel,a,b,out);

$dumpvars(2,mux_test);

sel=0;b={`width{1'b0}};a={`width{1'b1}};

#5sel=0;b={`width{1'b1}};a={`width{1'b0}};

#5sel=1;b={`width{1'b0}};a={`width{1'b1}};

#5sel=1;b={`width{1'b1}};a={`width{1'b0}};

#5 $finish;

end endmodule

四、仿真结果与波形

LAB 2:简单时序逻辑电路的设计一、二、实验目的 实验原理 掌握基本时序逻辑电路的实现。

在Verilog HDL中,相对于组合逻辑电路,时序逻辑电路也有规定的表述方式。在可综合的Verilog HDL模型中,我们常使用always块和@(posedge clk)或@(negedge clk)的结构来表述时序逻辑。

在always块中,被赋值的信号都必须定义为reg型,这是由时序逻辑电路的特点所决定的对于reg型数据,如果未对它进行赋值,仿真工具会认为它是不定态。为了正确地观察到仿真结果,在可综合的模块中我们通常定义一个复位信号rst-,当它为低电平时对电路中的寄存器进行复位。

三、源代码

counter.v `timescale 1 ns/100 ps module counter(cnt,clk,data,rst_,load);output[4:0]cnt;input [4:0]data;input

clk;input

rst_;input

load;reg

[4:0]cnt;

always@(posedge clk or negedge rst_)

if(!rst_)

#1.2 cnt<=0;

else

if(load)

cnt<=#3 data;

else

cnt<=#4 cnt + 1;

endmodule

counter_test.v `timescale 1 ns/1 ns module counter_test;

wire[4:0]cnt;

reg [4:0]data;

reg

rst_;

reg

load;

reg

clk;

counter c1

(.cnt(cnt),.clk(clk),.data(data),.rst_(rst_),.load(load));

initial begin

clk=0;

forever begin

#10 clk=1'b1;

#10 clk=1'b0;

end

end

initial begin

$timeformat(-9,1,“ns”,9);

$monitor(“time=%t,data=%h,clk=%b,rst_=%b,load=%b,cnt=%b”,$stime,data,clk,rst_,load,cnt);

$dumpvars(2,counter_test);

end task expect;input [4:0]expects;

if(cnt!==expects)begin

$display(“At time %t cnt is %b and should be %b”,$time,cnt,expects);

$display(“TEST FAILED”);

$finish;

end endtask initial begin

@(negedge clk)

{rst_,load,data}=7'b0_X_XXXXX;@(negedge clk)expect(5'h00);

{rst_,load,data}=7'b1_1_11101;@(negedge clk)expect(5'h1D);

{rst_,load,data}=7'b1_0_11101;

repeat(5)@(negedge clk);

expect(5'h02);

{rst_,load,data}=7'b1_1_11111;@(negedge clk)expect(5'h1F);

{rst_,load,data}=7'b0_X_XXXXX;@(negedge clk)expect(5'h00);

$display(“TEST PASSED”);

$finish;

end endmodule

四、仿真结果与波形

五、思考题

该电路中,rst-是同步还是异步清零端?

在counter.v的always块中reset没有等时钟,而是直接清零。所以是异步清零端。

LAB 3:简单时序逻辑电路的设计一、二、实验目的 实验原理 使用预定义的库元件来设计八位寄存器。

八位寄存器中,每一位寄存器由一个二选一MUX和一个触发器dffr组成,当load=1,装载数据;当load=0,寄存器保持。对于处理重复的电路,可用数组条用的方式,使电路描述清晰、简洁。

三、源代码

clock.v `timescale 1 ns /1 ns module clock(clk);reg clk;output clk;initial begin clk=0;forever begin #10 clk=1'b1;#10 clk=1'b0;end end endmodule

mux及dffr模块调用代码

mux mux7(.out(n1[7]),.sel(load),.b(data[7]),.a(out[7]));dffr dffr7(.q(out[7]),.d(n1[7]),.clk(clk),.rst_(rst_));mux mux6(.out(n1[6]),.sel(load),.b(data[6]),.a(out[6]));dffr dffr6(.q(out[6]),.d(n1[6]),.clk(clk),.rst_(rst_));mux mux5(.out(n1[5]),.sel(load),.b(data[5]),.a(out[5]));dffr dffr5(.q(out[5]),.d(n1[5]),.clk(clk),.rst_(rst_));mux mux4(.out(n1[4]),.sel(load),.b(data[4]),.a(out[4]));dffr dffr4(.q(out[4]),.d(n1[4]),.clk(clk),.rst_(rst_));

mux mux3(.out(n1[3]),.sel(load),.b(data[3]),.a(out[3]));dffr dffr3(.q(out[3]),.d(n1[3]),.clk(clk),.rst_(rst_));mux mux2(.out(n1[2]),.sel(load),.b(data[2]),.a(out[2]));dffr dffr2(.q(out[2]),.d(n1[2]),.clk(clk),.rst_(rst_));mux mux1(.out(n1[1]),.sel(load),.b(data[1]),.a(out[1]));dffr dffr1(.q(out[1]),.d(n1[1]),.clk(clk),.rst_(rst_));mux mux0(.out(n1[0]),.sel(load),.b(data[0]),.a(out[0]));dffr dffr0(.q(out[0]),.d(n1[0]),.clk(clk),.rst_(rst_));

例化寄存器

register r1(.data(data),.out(out),.load(load),.clk(clk),.rst_(rst_));例化时钟

clock c1(.clk(clk));

添加检测信号 initial begin $timeformat(-9,1,“ns”,9);$monitor(“time=%t,clk=%b,data=%h,load=%b,out=%h”, $stime,clk,data,load,out);$dumpvars(2,register_test);end

四、仿真结果与波形

LAB 4:用always块实现较复杂的组合逻辑电路

一、实验目的

掌握用always实现组合逻辑电路的方法;

了解assign与always两种组合逻辑电路实现方法之间的区别。

二、实验原理

仅使用assign结构来实现组合逻辑电路,在设计中会发现很多地方显得冗长且效率低下。适当地使用always来设计组合逻辑,会更具实效。

本实验描述的是一个简单的ALU指令译码电路的设计示例。它通过对指令的判断,对输入数据执行相应的操作,包括加、减、或和传数据,并且无论是指令作用的数据还是指令本身发生变化,结果都要做出及时的反应。

示例中使用了电平敏感的always块,电平敏感的触发条件是指在@后括号内电平列表的任何一个电平发生变化就能触发always块的动作,并且运用了case结构来进行分支判断。

在always中适当运用default(在case结构中)和else(子if…else结构中),通常可以综合为纯组合逻辑,尽管被赋值的变量一定要定义为reg型。如果不使用default或else对缺省项进行说明,易产生意想不到的锁存器。

三、源代码

电路描述

always@(opcode or data or accum)begin if(accum==8'b00000000)#1.2 zero=1;else #1.2 zero=0;

case(opcode)PASS0: #3.5 out =accum;PASS1: #3.5 out =accum;ADD: #3.5 out = data + accum;AND: #3.5 out =data&accum;XOR: #3.5 out =data^accum;PASSD: #3.5 out=data;PASS6:#3.5 out=accum;PASS7:#3.5 out=accum;default:#3.5 out=8'bx;endcase end

四、仿真结果与波形

LAB 5:存储器电路的设计一、二、实验目的 实验原理 设计和测试存储器电路。

本实验中,设计一个模块名为mem的存储器仿真模型,该存储器具有双线数据总线及异步处理功能。由于数据是双向的,所以要注意,对memory的读写在时序上要错开。

三、源代码

自行添加的代码

assign data=(read)?memory[addr]:8'hZ;

always @(posedge write)begin memory[addr]<=data[7:0];end

四、仿真结果与波形

LAB 6:设计时序逻辑时采用阻塞赋值与非阻塞赋值的区别

一、实验目的

明确掌握阻塞赋值与非阻塞赋值的概念和区别; 了解阻塞赋值的使用情况。

二、实验原理

在always块中,阻塞赋值可以理解为赋值语句是顺序执行的,而非阻塞赋值可以理解为并发执行的。实际时序逻辑设计中,一般情况下非阻塞赋值语句被更多的使用,有时为了在同一周期实现相互关联的操作,也使用阻塞赋值语句。

三、源代码

blocking.v `timescale 1 ns/ 100 ps

module blocking(clk,a,b,c);

output[3:0]b,c;

input [3:0]a;

input

clk;

reg

[3:0]b,c;

always@(posedge clk)

begin

b =a;

c =b;

$display(“Blocking: a=%d,b=%d,c=%d.”,a,b,c);

end endmodule

non_blocking.v `timescale 1 ns/ 100 ps module non_blocking(clk,a,b,c);

output[3:0] b,c;input[3:0] a;input clk;reg [3:0]b,c;always @(posedge clk)begin b<=a;c<=b;$display(“Non_blocking:a=%d,b=%d,c=%d”,a,b,c);end endmodule compareTop.v `timescale 1 ns/ 100 ps module compareTop;wire [3:0] b1,c1,b2,c2;reg[3:0]a;reg clk;initial begin clk=0;forever #50 clk=~clk;end initial $dumpvars(2,compareTop);initial begin a=4'h3;$display(“_______________________________”);# 100 a =4'h7;$display(“_______________________________”);# 100 a =4'hf;$display(“_______________________________”);# 100 a =4'ha;$display(“_______________________________”);# 100 a =4'h2;$display(“_______________________________”);# 100 $display(“_______________________________”);$finish;end non_blocking nonblocking(clk,a,b2,c2);blocking blocking(clk,a,b1,c1);endmodule

四、仿真结果与波形

LAB 7:利用有限状态机进行复杂时序逻辑的设计一、二、实验目的 实验原理 掌握利用有限状态机(FSM)实现复杂时序逻辑的方法。

控制器是CPU的控制核心,用于产生一系列的控制信号,启动或停止某些部件。CPU何时进行读指令,何时进行RAM和I/O端口的读写操作等,都由控制器来控制。

三、源代码

补充代码

nexstate<=state+1'h01;case(state)1:begin sel=1;rd=0;ld_ir=0;inc_pc=0;halt=0;ld_pc=0;data_e=0;ld_ac=0;wr=0;end 2:begin sel=1;rd=1;ld_ir=0;inc_pc=0;halt=0;ld_pc=0;data_e=0;ld_ac=0;wr=0;end 3:begin sel=1;rd=1;ld_ir=1;inc_pc=0;halt=0;ld_pc=0;data_e=0;ld_ac=0;wr=0;end 4:begin sel=1;rd=1;ld_ir=1;inc_pc=0;halt=0;ld_pc=0;data_e=0;ld_ac=0;wr=0;end 5:begin sel=0;rd=0;ld_ir=0;inc_pc=1;ld_pc=0;data_e=0;ld_ac=0;wr=0;if(opcode==`HLT)halt=1;end 6:begin sel=0;rd=alu_op;ld_ir=0;inc_pc=0;halt=0;ld_pc=0;data_e=0;ld_ac=0;wr=0;end 7:begin sel=0;rd=alu_op;ld_ir=0;halt=0;data_e=!alu_op;ld_ac=0;wr=0;if(opcode==`SKZ)inc_pc<=zero;if(opcode==`JMP)ld_pc=1;end 0:begin sel=0;rd=alu_op;ld_ir=0;halt=0;data_e=!alu_op;ld_ac=alu_op;inc_pc=(opcode==`SKZ)&zero||(opcode==`JMP);if(opcode==`JMP)ld_pc=1;if(opcode==`STO)wr=1;end //default:begin sel=1'bZ;rd=1'bZ;ld_ir=1'bZ;inc_pc=1'bZ;halt=1'bZ;ld_pc=1'bZ;data_e=1'bZ;ld_ac=1'bZ;wr=1'bZ;end endcase end

control_test.v /***************************** * TEST BENCH FOR CONTROLLER * *****************************/

`timescale 1 ns / 1 ns

module control_test;

reg [8:0] response [0:127];

reg [3:0] stimulus [0:15];

reg [2:0] opcode;

reg

clk;

reg

rst_;

reg

zero;

integer

i,j;

reg[(3*8):1] mnemonic;

// Instantiate controller

control c1(rd , wr , ld_ir , ld_ac , ld_pc , inc_pc , halt , data_e , sel , opcode , zero , clk , rst_);

// Define clock

initial begin

clk = 1;

forever begin

#10 clk = 0;

#10 clk = 1;

end

end

// Generate mnemonic for debugging purposes

always @(opcode)

begin

case(opcode)

3'h0

: mnemonic = “HLT”;

3'h1

: mnemonic = “SKZ”;

3'h2

: mnemonic = “ADD”;

3'h3

: mnemonic = “AND”;

3'h4

: mnemonic = “XOR”;

3'h5

: mnemonic = “LDA”;

3'h6

: mnemonic = “STO”;

3'h7

: mnemonic = “JMP”;

default : mnemonic = “???”;

endcase

end

// Monitor signals

initial

begin

$timeformat(-9, 1, “ ns”, 9);

$display(“ time

rd wr ld_ir ld_ac ld_pc inc_pc halt data_e sel opcode zero state”);

$display(“--------------------------------------------------------------”);//

$shm_open(“waves.shm”);//

$shm_probe(“A”);//

$shm_probe(c1.state);

end

// Apply stimulus

initial

begin

$readmemb(“stimulus.pat”, stimulus);

rst_=1;

@(negedge clk)rst_ = 0;

@(negedge clk)rst_ = 1;

for(i=0;i<=15;i=i+1)

@(posedge ld_ir)

@(negedge clk)

{ opcode, zero } = stimulus[i];

end

// Check response

initial

begin

$readmemb(“response.pat”, response);

@(posedge rst_)

for(j=0;j<=127;j=j+1)

@(negedge clk)

begin

$display(“%t %b %b %b

%b

%b

%b

%b

%b %b

%b

%b”,$time,rd,wr,ld_ir,ld_ac,ld_pc,inc_pc,halt,data_e,sel,opcode,zero,c1.state);

if({rd,wr,ld_ir,ld_ac,ld_pc,inc_pc,halt,data_e,sel}!==

response[j])

begin : blk

reg [8:0] r;

r = response[j];

$display("ERRORTEST1 PASSED!

111_00000

// 18

JMP BEGIN //run test again

@1A 00000000

// 1A

DATA_1:

//constant 00(hex)

11111111

// 1B

DATA_2:

//constant FF(hex)

10101010

// 1C

TEMP:

//variableTEST2 PASSED!

111_00000

// 11

JMP BEGIN

//run test again

@1A 00000001

// 1A

DATA_1:

//constant 1(hex)

10101010

// 1B

DATA_2:

//constant AA(hex)

11111111

// 1C

DATA_3:

//constant FF(hex)

00000000

// 1D

TEMP:

CPUtest3.dat //opcode_operand // addr

assembly code //--------------//-------------------------

111_00011

// 00

JMP LOOP

//jump to the address of LOOP @03 101_11011

// 03

LOOP:

LDA FN2

//load value in FN2 into accum

110_11100

// 04

STO TEMP

//store accumulator in TEMP

010_11010

// 05

ADD FN1

//add value in FN1 to accumulator

110_11011

// 06

STO FN2

//store result in FN2

101_11100

// 07

LDA TEMP

//load TEMP into the accumulator

110_11010

// 08

STO FN1

//store accumulator in FN1

100_11101

// 09

XOR LIMIT //compare accumulator to LIMIT

001_00000

// 0A

SKZ

//if accum = 0, skip to DONE

111_00011

// 0B

JMP LOOP

//jump to address of LOOP

000_00000

// 0C

DONE:

HLT

//end of program

101_11111

// 0D

AGAIN: LDA ONE

110_11010

// 0E

STO FN1

101_11110

// 0F

LDA ZERO

110_11011

// 10

STO FN2

111_00011

// 11

JMP LOOP

//jump to address of LOOP

@1A 00000001

// 1A

FN1:

//variablestores 2nd Fib.No.00000000

// 1C

TEMP:

//temporary variable

10010000

// 1D

LIMIT:

//constant 144stores 1st Fib.No.00000101

// 1B

data2:

//5

variablemax value

00000110

// 1E

LIMIT:

// 6

constant 1

11111111

// 1F

AND1:

//FF and

四、仿真结果与波形

第二部分 电路综合一、二、三、四、实验目的 实验内容 源代码

门级电路仿真结果与波形 掌握逻辑综合的概念和流程,熟悉采用Design Compiler进行逻辑综合的基本方法。采用SYNOPSYS公司的综合工具Design Compiler对实验7的control.v做综合。与实验指导书中相同。

五、思考题

1.control_pad.v文件是verilog语言及的描述还是结构化的描述?

是结构化的描述。

2.control_pad.sdf文件中,对触发器的延迟包括哪些信息?

包括对逻辑单元和管脚的上升/下降时延的最大值、最小值和典型值。

第三部分 版图设计一、二、三、四、实验目的 实验内容 源代码

仿真结果与波形 掌握版图设计的基本概念和流程,熟悉采用Sysnopsys ICC工具进行版图设计的方法。对电路综合输出的门级网表control_pad.v进行布局布线。与实验指导书中相同。布局规划后结果

未产生core ring和mesh前

产生core ring和mesh后

电源线和电影PAD连接后

filler PAD填充后

布局后结果

时钟树综合后结果

布线后结果

寄生参数的导出和后仿

五、思考题

1.简述ICC在design setup阶段的主要工作。

创建设计库,读取网表文件并创建设计单元,提供并检查时间约束,检查时钟。在对之前的数据与信息进行读取与检查后保存设计单元。2.为什么要填充filler pad?

filler pad把分散的pad单元连接起来,把pad I/O区域供电连成一个整体。使它们得到持续供电并提高ESD保护能力。3.derive_pg_connection的作用是什么?

描述有关电源连接的信息。4.简述floorplan的主要任务。

对芯片大小、输入输出单元、宏模块进行规划,对电源网络进行设计。5.简述place阶段的主要任务。

对电路中的延时进行估计与分析,模拟时钟树的影响,按照时序要求,对标准化单元进行布局。

6.简述CTS的主要步骤。

设置时钟树公共选项;综合时钟树;重新连接扫描链;使能传播时钟;Post-CTS布局优化;优化时钟偏移;优化时序。

实验总结

经过数周的ASIC专业实验,我对芯片设计流程、Verilog HDL语言、Linux基本指令和Vi文本编辑器有了基本的了解。虽然之前对芯片设计、VHDL一无所知,但通过实验初步熟悉了ASIC的体系结构和VHDL的基本语法,对电路中时钟、寄生参数、元件布局带来的影响也有了了解。我在实验中也遇到了许多问题,但我在老师、助教、同学的帮助下解决了这些问题,也有了更多收获。通过这次ASIC专业实验,我加深了对本专业的认识。我会继续努力成为合格的电子人。

第二篇:北邮电子院嵌入式实验报告大四上

嵌入式实验报告

学院: 电子工程学院

一、实验目的

1、了解嵌入式系统及其相关基础知识。

2、了解宿主PC机与PXA270目标版,能正确连接宿主PC机与PXA270目标版。

3、学会在宿主机上安装Linux操作系统——RedHat9.0。、4、学会建立宿主PC机端的开发环境。

5、学会配置宿主PC机端的超级终端。

6、配置宿主PC机端的TFTP服务,并开通此服务。

7、配置宿主PC机端的NFS服务,并开通此服务。

8、学会简单Linux驱动程序的设计。

二、实验内容

(一)基本实验

实验一到六为基础实验,主要是为了在熟悉实验操作平台的同时为后续实验搭建好软、硬件环境,配置好相关的协议、服务。

其中实验一是各个硬件的互联,搭建好了实验的硬件环境。实验二是在宿主PC端安装虚拟机,提供了实验需要的Linux操作系统。实验三是宿主PC端开发环境的安装与配置。

实验四是配置宿主PC机端的超级终端,使PC机与PXA270目标板之间可以通过串口通讯。在每次重启宿主PC机时,都需要重新将超级终端挂载到虚拟机上,挂载之前须通过ifconfig命令查看该机的IP地址,若其已经复位,须用命令:ifconfig eth0 192.168.0.100 up重置宿主PC机的IP地址。挂载虚拟机的代码为:

root ifconfig eth0 192.168.0.50 up mount –o nolock 192.168.0.100:/ /mnt 实验五是配置宿主PC机的TFTP服务。TFTP是简单文件传输协议。每次重启宿主PC机时,都要重启该服务,重启命令为:

service xinetd restart。

实验六是配置宿主PC机端NFS服务。NFS是指网络文件系统,它实现了文件在不同的系统间使用。当使用者想用远端档案时,只需调用“mount”就可以远端系统挂接在自己的档案系统之下。每次重启宿主PC机时,也都要重启该服务,重启命令为: service nfs restart service nfs restart

(二)基本接口实验

实验

十二、简单设备驱动程序

本次实验的目的是让我们动手实践一个简单的字符型设备驱动程序,学习Linux驱动程序构架,学习在应用程序中调用驱动。驱动程序代码及注释为: // 头文件

#include #include #include #include #include #include #include #define SIMPLE_HELLO_MAJOR 96 // 定义主设备号HELLO DEVICE MAJOR #define OURS_HELLO_DEBUG // 定义标识符

#define VERSION “PXA2700EP-SIMPLE_HELLO-V1.00-060530” // 定义版本号 void showversion(void)//显示版本的函数 { printk(“***************************************”);printk(“t %s tn”,VERSION);printk(“***************************************”);}

/*-------read:用于在指定文件描述符中读取数据 file:是文件指针 buf:读取数据缓存区 count:请求传输的字节数 f_ops:文件当前偏移量

当读取标识符OURS_HELLO_DEBUG时,打印信息,然后返回count----------*/ ssize_t SIMPLE_HELLO_read(struct file * file ,char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_HELLO_DEBUG

printk(“SIMPLE_HELLO_read[--kernel--]n”);#endif return count;}

/*-----write:用于向打开的文件写数据 file:是文件指针 buf:写入数据缓存区 count:求传输的字节数 f_ops:文件当前偏移量

当读取标识符OURS_HELLO_DEBUG时,打印信息,然后返回count----------*/ ssize_t SIMPLE_HELLO_write(struct file * file ,const char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_HELLO_DEBUG

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

return count;}

/*-----ioctl:对设备的I/O通道进行管理的函数 inode:设备节点

flip:打开的一个文件

cmd:驱动程序的特殊命令编号 data:接收剩余参数

----------*/ ssize_t SIMPLE_HELLO_ioctl(struct inode * inode ,struct file * file, unsigned int cmd, long data){ #ifdef OURS_HELLO_DEBUG

printk(“SIMPLE_HELLO_ioctl[--kernel--]n”);#endif return 0;}

/*----------open:打开函数

inode:打开文件所对应的i节点,获取从设备号 flip:打开的一个文件

open()方法最重要的是调用了宏MOD_INC_USE_COUNT,这个宏主要用来使驱动程序使用计数器,避免不正确卸载程序

----------*/ ssize_t SIMPLE_HELLO_open(struct inode * inode ,struct file * file){ #ifdef OURS_HELLO_DEBUG

printk(“SIMPLE_HELLO_open[--kernel--]n”);#endif MOD_INC_USE_COUNT;return 0;}

/*----------released:关闭函数

Inode:打开文件所对应的i节点,主要获取从设备号 flip:打开的一个文件

release()方法最重要的是调用了宏MOD_DEC_INC_USE_COUNT,这个宏主要用来减少驱动程序使用计数器

----------*/ ssize_t SIMPLE_HELLO_release(struct inode * inode ,struct file * file){ #ifdef OURS_HELLO_DEBUG

printk(“SIMPLE_HELLO_release[--kernel--]n”);#endif MOD_DEC_INC_USE_COUNT;return 0;}

struct file_operations HELLO_ops ={ // SIMPLE_HELLO设备向系统注册

open: SIMPLE_HELLO_open, read: SIMPLE_HELLO_read, write: SIMPLE_HELLO_write, ioctl: SIMPLE_HELLO_ioctl, release: SIMPLE_HELLO_release, };

/*----------INIT:驱动程序初始化

devfs_register_chrdev(SIMPLE_HELLO_MAJOR,“hello_serial_ctl”,& HELLO_ops)最为主要

devfs_register_chrdev注册设备驱动程序,包括主设备号、驱动程序名、结构体指针----------*/ static int __init HW_ HELLO_init(void){ int ret =-ENODEV;

ret = devfs_register_chrdev(SIMPLE_HELLO_MAJOR, “hello_serial_ctl”,& HELLO_ops);

showversion();

if(ret<0)

{

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

}

else

{

printk(“pxa270 hello_driver register success!![--kernel--]n”);

} return ret;}

static int __init pxa270_ HELLO_init(void)//模块初始化函数,调用HW_ HELLO_init 函数

{ int ret =-ENODEV;

#ifdef OURS_HELLO_DEBUG

printk(“pxa270_ HELLO_init[--kernel--]n”);

#endif ret = HW_ HELLO_init();if(ret)return ret;return 0;}

/*----------模块卸载函数

devfs_unregister_chrdev(SIMPLE_HELLO_MAJOR,“hello _ctl”)最为主要 devfs_unregister_chrdev卸载设备驱动程序,包括主设备号、驱动程序名

----------*/ static void __exit cleanup_ HELLO_ctl(void){ #ifdef OURS_HELLO_DEBUG

printk(“cleanup_HELLO_ctl[--kernel--]n”);#endif devfs_unregister_chrdev(SIMPLE_HELLO_MAJOR, “hello_ctl”);}

MODULE_DESCRIPTION(“simple hello driver module”);//描述信息 MODULE_AUTHOR(“liduo”);

//驱动程序作者姓名 MODULE_LICENSE(“GPL”);module_init(pxa270_HELLO_init);

//指定驱动程序初始化函数 module_exit(cleanup _HELLO_ctl);

//指定驱动程序卸载函数

Makefile文件代码:

#TOPDIR:=$(shell cd..;pwd)TOPDIR:=.KERNELDIR=/pxa270_linux/linux INCLUDEDIR=$(KERNELDIR)/include CROSS_COMPILE=arm-linux-

AS =$(CROSS_COMPILE)as LD =$(CROSS_COMPILE)ld CC =$(CROSS_COMPILE)gcc CPP =$(CC)-E AR =$(CROSS_COMPILE)ar NM =$(CROSS_COMPILE)nm STRIP =$(CROSS_COMPILE)strip OBJCOPY=$(CROSS_COMPILE)objcopy OBJDUMP=$(CROSS_COMPILE)objdump

CFLAGS+=-I..CFLAGS+=-Wall –O –D_KERNEL_-DMODULE –I$(INCLUDEDIR)

TARGET = pxa270_hello_drv.o modules: $(TARGET)

all: $(TARGET)

pxa270_hello_drv.o:pxa270_hello_drv.c $(CC)-c $(CFLAGS)$^-o $@

clean: rm-f *.o *~ core.depend Makefile文件的内容用于执行编译工作,一个Makefile文件包括:① 由make工具创建的目标体(target),通常是目标文件或可执行文件;② 要创建目标体所依赖的文件(dependency_file);③ 创建每个目标需要运行的命令(command)。

以上两个文件编辑完成后后,用make modules编译驱动程序,编写测试文件simple_test_driver.c,然后GCC编辑器编译测试程序生成测试文件。成功生成测试文件后用超级终端开始挂载,加载驱动程序,使用命令./test测试,观察测试结果,实验完成。

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

本实验是让我们在linux系统中插入自己的驱动程序,调用它。实现用CPU GPIO控制外部LED,利用PXA270核心板上的LED验证我们的工作。驱动程序代码:

驱动程序代码与实验十二无大区别,下面列出需要补充的代码。

一、补充代码

补充代码1:

#ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_write [--kernel--]n”);#endif return count;

补充代码2:

#ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_open [--kernel--]n”);#endif

补充代码3:

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, 不同之处:GPIO_LED,主文件名、二、Makefile文件:

将实验十二相关代码作如下修改即可: TARGET = pxa270_gpio_led_drv.o modules: $(TARGET)

all: $(TARGET)

pxa270_gpio_led_drv.o:pxa270_gpio_led_drv.c $(CC)-c $(CFLAGS)$^-o $@

三、作业代码

要求:使得目标板的核心板上的LED闪烁产生亮7秒,灭5秒的效果。作业主要代码:

while(1)

{ ioctl(fd,LED_OFF);

sleep(5);//原来为sleep(1);

ioctl(fd,LED_ON);sleep(7);//原来为sleep(1); }

不同之处:改变代码中加粗位置括号数字,可以改变灯亮和熄灭的时间比

四、测试显示

测试时,超级终端上的显示如下:

实验十四 中断实验

本实验是让我们学习中断的相关概念,以及Linux系统是如何处理中断的,并且学会编写获取和处理外中断的驱动程序。

一、补充代码

补充代码1:

printk(“*****************************************n”);printk(“t %s tn”,VERSION);printk(“************************************************nn”);补充代码2:

#ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_read [--kernel--]n”);#endif return count;

补充代码3:

#ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_write [--kernel--]n”);#endif return count;

补充代码4:

open: SIMPLE_INT_open, read: SIMPLE_INT_read, write: SIMPLE_INT_write, ioctl: SIMPLE_INT_ioctl, release: SIMPLE_INT_release, 二、Makefile文件如实验十三做相应修改。

三、测试时,超级终端上显示如下:

实验十五 数码管显示驱动实验

本实验中,我们要编驱动程序以实现在Linux系统下控制LED数码管的显示。

一、补充代码

补充代码1:

printk(“*****************************************n”);printk(“t %s tn”,VERSION);printk(“************************************************nn”);

补充代码2: #ifdef OURS_HELLO_DEBUG printk(“SERIAL_LED_read [--kernel--]n”);#endif return count;

补充代码3: #ifdef OURS_HELLO_DEBUG printk(“SERIAL_LED_write [--kernel--]n”);#endif return count;

补充代码4: #ifdef OURS_HELLO_DEBUG printk(“SERIAL_LED_ioctl [--kernel--]n”);#endif return 0;

补充代码5: #ifdef OURS_HELLO_DEBUG printk(“SERIAL_LED_open [--kernel--]n”);#endif MOD_INC_USE_COUNT;return 0;

补充代码6: #ifdef OURS_HELLO_DEBUG printk(“SERIAL_LED_release [--kernel--]n”);#endif MOD_DEC_USE_COUNT;return 0;

补充代码7: open: SERIAL_LED_open, read: SERIAL_LED_read, write: SERIAL_LED_write, ioctl: SERIAL_LED_ioctl, release: SERIAL_LED_release

补充代码8: 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 %dn [--kernel--]”,ret);return ret;} else { printk(“pxa270 serial_led_driver register success!![--kernel--]n”);} return ret;

补充代码9: 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: #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);

二、Makefile文件与实验十四相同,只需作相应修改即可

三、作业代码

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

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

{ data[0] = buf[9-count];//原来为data[0] = buf[count] ret=write(fd,data,1);sleep(1);} 修改之处:将显示的数有buf[count]改为buf[9-count],实现反向循环显示。

2、实现目标板上的LED数码管循环显示数字2、4、6、8、0或者8、6、4、2、0。代码: for(count=0;count<10;count+=2)//原来为count++

{data[0] = buf[count];ret=write(fd,data,1);sleep(1);}

修改之处:修改count的变化方式,让其每次增加2,而不是1,使0、2、4、6、8循环显示,如要循环显示8、6、4、2、0的话,只要在上述代码中将buf[count]改为buf[8-count]即可。

四、测试显示:

测试时,显示如下:

作业1: 作业2:

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

本实验要求我们学会编写驱动程序,实现在Linux系统下控制LED点阵显示,并在此基础上稍加改进,实现对LED的控制。驱动程序代码:

一、补充代码

补充代码1:

printk(“*****************************************n”);printk(“t %s tn”,VERSION);printk(“************************************************nn”);

补充代码2:

#ifdef OURS_LED_DEBUG printk(“SIMPLW_LED_read [--kernel--]n”);#endif return count;

补充代码3:

#ifdef OURS_LED_DEBUG printk(“SIMPLE_LED_ioctl [--kernel--]n”);#endif return 0;

补充代码4:

open: SIMPLE_LED_open, read: SIMPLE_LED_read, write: SIMPLE_LED_write, ioctl: SIMPLE_LED_ioctl, release: SIMPLE_LED_release

补充代码5:

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:

#ifdef OURS_LED_DEBUG printk(“cleanup_LED_ctl [--kernel--]n”);#endif devfs_unregister_chrdev(SIMPLE_LED_MAJOR, “led_ctl”);

二、Makefile程序仍然可以用前一个实验的,只要把相关函数名改了就可以,此处不再赘述。

三、作业代码

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

for(i=1;i<=4;i++){ //原来为i<8

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;

} //原来为r=r<<1

修改之处:外层for循环中间i<8改为i<4,同时,将else中的r=r<<1改为r<<2。这样就可以让点阵在显示时跳跃一行进行显示。

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

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;//原来此处为c=c<<1 buf[1]=~r;//原来此处为buf[1]=~c } r = 1;//原来此处为c=1 c = c<<1;//原来此处为r=r<<1 修改之处(现对于最初的测试程序,而不是作业1的测试程序):将r和c 进行对调。实现将横和竖的对调,已达到竖方向扫描的目的。四、测试显示

测试时,超级终端显示如下:

作业1: 作业2:

实验十七 AD驱动程序

本实验要求我们学会编写驱动程序对模拟量输入进行采集,并转换为数字量显示在超级终端上,从而实现AD转换。

驱动程序代码

一、补充代码

补充代码1:

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

printk(“************************************************nn”);

补充代码2:

#ifdef OURS_HELLO_DEBUG printk(“SIMPLE_HELLO_read [--kernel--]n”);#endif return count;

补充代码3:

#ifdef OURS_HELLO_DEBUG printk(“SIMPLE_HELLO_write [--kernel--]n”);#endif return count;

补充代码4:

#ifdef OURS_HELLO_DEBUG printk(“SIMPLE_HELLO_open [--kernel--]n”);#endif MOD_INC_USE_COUNT;return 0;

补充代码5:

#ifdef OURS_HELLO_DEBUG printk(“SIMPLE_HELLO_release [--kernel--]n”);#endif MOD_DEC_USE_COUNT;return 0;

补充代码6:

open: SIMPLE_HELLO_open, read: SIMPLE_HELLO_read, write: SIMPLE_HELLO_write, ioctl: SIMPLE_HELLO_ioctl, release: SIMPLE_HELLO_release

补充代码7:

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 %dn [--kernel--]”,ret);return ret;} else { printk(“pxa270 serial_led_driver register success!![--kernel--]n”);} return ret;

补充代码8:

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:

#ifdef OURS_HELLO_DEBUG printk(“cleanup_AD_ctl [--kernel--]n”);#endif devfs_unregister_chrdev(ADCTL_MAJOR, “ad_ctl”);

二、Makefile文件可以用前一个程序的文件,只要将相应部分的代码修改即可

三、作业代码

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

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 = %dtval1 = %dn”,val0,val1;usleep(500000);

}

修改之处:只需交换AD1和AD0即可实现输出通道的改变。四、测试时显示

测试时、超级终端显示如下:

实验十八 DA驱动程序

本实验要求我们编写驱动程序,实现将数字信号转换成模拟信号并在示波器上显示出模拟信号波形,即实现DA转换。驱动程序代码:

一、补充代码

补充代码1:

#include“../AD/pxa_ad_drv.h” /引用AD驱动程序的头文件/

补充代码2:

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

printk(“************************************************nn”);

补充代码3:

#ifdef OURS_DA_DEBUG printk(“SIMPLE_DA_read [--kernel--]n”);#endif return count;

补充代码4:

#ifdef OURS_DA_DEBUG printk(“SIMPLE_DA_write [--kernel--]n”);#endif return count;

补充代码5:

#ifdef OURS_DA_DEBUG printk(“SIMPLE_DA_ioctl [--kernel--]n”);#endif return 0;

补充代码6:

#ifdef OURS_DA_DEBUG printk(“SIMPLE_DA_open [--kernel--]n”);#endif MOD_INC_USE_COUNT;return 0;

补充代码7:

open: SIMPLE_DA_open, read: SIMPLE_DA_read, write: SIMPLE_DA_write, ioctl: SIMPLE_DA_ioctl, release: SIMPLE_DA_release

补充代码8:

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 %dn [--kernel--]”,ret);return ret;} else { printk(“pxa270 serial_led_driver register success!![--kernel--]n”);} return ret;

补充代码9:

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:

#ifdef OURS_DA_DEBUG printk(“cleanup_DA_ctl [--kernel--]n”);#endif devfs_unregister_chrdev(SIMPLE_DA_MAJOR, “DA_ctl”);补充代码11:

MODULE_DESCRIPTION(“serial_led driver module”);MODULE_AUTHOR(“liduo”);MODULE_LICENSE(“GPL”);module_init(pxa270_DA_CTL_init);module_exit(cleanup_DA_ctl);

二、Makefile文件可以继续用前面程序Mekefile的代码,只需要将相应部分的代码修改即可。

三、作业代码

要求:输出三角波。代码:(需要修改部分)

//---------------------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

x=(j/POINT)*(5*M_PI);//此处原来为x=sin((j/POINT

//*(2*M_PI))#ifdef OURS_DEBUG printf(“%ft”,x);#endif buf[j] =(unsigned char)255*(x/2+1)/2;#ifdef OURS_DEBUG printf(“%xn”, buf[j]);#endif } printf(“create sin waven”);printf(“Use”Ctrl + c“quit the functionn”);while(1){ c = buf;for(j=0;j

四、测试显示:(以下为三角波)

(以下为sin)

三、实验总结:

在本次嵌入式实验中,我们首先在老师的指导下了解了嵌入式系统,初步接触了Linux环境。我们的实验板是OURS-PXA270-EP,它是一款基于INTEL XSCALE PXA270处理器,针对高校嵌入式系统教学和实验科研的平台。这款设备主要包括核心板与底板两个部分,核心板主要集成了高速的PXA270 CPU,配套的存储器,网卡等设备;底板主要是各种类型的接口与扩展口。

了解了实验的平台后,在接下来的基本实验中我们学会了嵌入式开发系统硬件环境的搭建、Linux操作系统RedHat9的安装、软件环境的搭建,以及配置超级终端,配置通讯服务。这些实验内容只要按照实验指导书上的步骤一步一步做即可,不会出现难以解决的问题,一般都会做的很顺利。有三个需要注意的地方时,在配置端口时,一定要确定实验箱接的是端口一,还是端口二。否则会出现无法建立呼叫的问题(其表现为超级终端接口内没有输出内容)。其次要确定虚拟机上网桥的设定是否正确。不然也会出现无法呼叫现象。最后,要确定网线是否连接上。在实验时,由于有些电脑的网线接口有断裂的现象,如果插口没接好的话,将会出现nfs连接错误。

在基本实验之后,进行的就是接口实验。总的来说,实验的难度不大。当然这是建立在对实验代码有一定理解的基础之上的。在实验十二中,我们对实验的接口代码规则已经有了一定的了解。而之后的几个实验都是基于实验十二进行相应的改动即可。所以完成下来难度不是很大。而对应的作业中,我们仅需要对测试代码进行相应的改写。在对c语言有一定的了解的前提下,可以很容易相应代码所实现的功能,仅需要对相应代码做些修改即可。

不过,值得注意的还有两点,第一:代码的编写一定要符合规则,同时,代码的输入要避免输入错误。否则,在需要一次一次编译一次次查看错误一次次改正错误,这会是个费时费力的工作。第二:每次实验时,需要从新设定虚拟机的ip,即每次实验开始时都需要重复做实验五实验六。不然在挂载时会出现无法挂载的现象。

通过这次实验,我对嵌入式编程有了更深层次的理解,加深了我对理论知识的认识,有助于今后的学习和工作。感谢黄惠英老师的细心指导。

第三篇:北邮数据库实验报告

数据库实验报告

(三)姓名:学号:班级:

1.用Transact-SQL语句、数据导入、SQL Server Management Studio(企业管理器)输入的方法对所给定的8张表的数据输入到数据库中。自行决定每张表的数据导入办法,但每种方法各针对二或三张表。

 Transact-SQL语句: 导入department,student, student_course表。

insertinto department select*from openrowset

('microsoft.jep.oledb.4.0','excel 5.0;hdr=yes;database=D:课件数据库database2.xls',department$);

insertinto student select*from openrowset

('microsoft.jep.oledb.4.0','excel 5.0;hdr=yes;database=D:课件数据库database2.xls',student$);

insertinto student_course select*from openrowset

('microsoft.jep.oledb.4.0','excel 5.0;hdr=yes;database=D:课件数据库database2.xls',student_course$);

 数据导入:

操作:选中数据库studentsdb,右键-任务-导入数据。导入book, class, course表。

SQL Server Management Studio: 操作:右键需要编辑的表,选择编辑前200行。

Teacher:

Teacher_course_class:

导入结果: Book:

Class:

Course:

Department:

Student:

Student_course:

Teacher:

Teacher_course_class:

2.用Transact-SQL向Course表中插入一条记录,course_name为空,看运行的结果。

SQL语句:

INSERTINTO course VALUES('dep02_s002', null,'dep02_s002', '72', '5', '4');运行结果:

分析:course_name有not null的约束,因此这条语句不能执行。

3.用Transact-SQL修改Course表中credit为5的记录,将其credit改为7, credit小于4的改为2,看运行的结果。

SQL语句:

update course set credit=7 where credit=5;执行结果:

分析:约束C1指定了credit的范围为1至6.SQL语句:

update course set credit=2 where credit<4;执行结果:

4.删除一条学生记录,看运行结果,对运行结果进行分析。SQL语句:

deletefrom student where student_id='g9940201';执行结果:

分析:因为有参照完整性约束,不能删除。

5.用Transact-SQL完成将编号为dep04_b001的课程的选修信息插入到一个新的选课信息表中。

SQL语句:

Creattablestudent_course2(course_idchar(20), student_idchar(20)gradeint, creditint, semesterint,school_yearchar(20),primarykey(course_id,student_id));

insertintostudent_course2 select*fromstudent_course wherecourse_id='dep04_b001';执行结果:

6.用Transact-SQL完成删除单片机原理课程的选课信息,分析运行结果。

SQL语句:

deletefrom student_course where course_id in(select course_id from course

where course_name='单片机原理')执行结果: 分析:所有课程号为dep04_s003的课程被删除。

本实验中遇到的问题和解决方法:

本实验的顺利完成需要预先作很多准备工作。以下就是我在遇到缺少组件accessdatabaseengine时的解决过程的记录。

AccessDatabaseEngine的安装

accessdatabaseengine用于和office连接,导入导出数据,本实验中需要导入excel文件。安装配合office的版本,我安装的是accessdatabaseengine2017(English)版本。安装32位版本,因office2016是32位。之前误操作安装了不能使用的老旧版本accessdatabaseengine2007,通过控制面板-应用程序卸载将其卸载了。安装accessdatabaseengine依然报错,是因为microsoftofficeclicktorun阻碍sqlserver的一些功能,需要将其卸载。这是微软推出的用于减少office打开速度的应用程序,安装office2016时会自动安装上,原理是开机时将一部分内容放到内存中,因此打开文件时会更快一些。检测自己的office是通过clickto run 还是MSI安装的,可以在word中点击文件-账户,查看产品信息,如果有下图中“office更新”这个选项,则说明安装过click to run。这个程序在控制面板-应用程序中找不到,因此用删除注册表的方式卸载。快捷键“win+R”输入“regedit”打开注册表编辑器,左边HKEY_CLASSES_ROOT-Installer-Product-00006开头的选项,有四个。单击这几个选项,在右侧查看详细信息,可以看到ProductNam是Microsoft Access database engine 2007(我原来误安装的老版本)。删除之前先备份注册表。方法一:选中要删除的文件,右键-导出,保存。只保存了要删除的文件。方法二:注册表编辑器,文件-导出,保存。保存了注册表所有信息。这是因为如果误删了重要文件会导致严重后果,可能需要重装系统,留此备份是为了可以恢复系统。

备份完之后,选中要删除的文件(00006开头的四个),右键-删除即可。回到Access database engine 32位的程序安装包,安装。我无法安装64位,可能是因为office是32位。安装成功之后就可以在sqlserver中导入excel文件了。

第四篇:北邮嵌入式实验报告

北京邮电大学

嵌入式系统开发实验报告

学院:

班级: 姓名: 学号:

序号:

目录

一、实验目的..............................................................................................1

二、实验设备..............................................................................................1

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

1.实验五..................................................................................................1 2.实验六..................................................................................................1 3.实验七..................................................................................................1

四、驱动程序..............................................................................................5

1.设备驱动程序的概念..........................................................................5 2.驱动程序结构......................................................................................6 3.设备注册和初始化..............................................................................7 4.设备驱动程序的开发过程..................................................................8

五、基本接口实验......................................................................................8

1.实验十二简单设备驱动程序..............................................................9 2.实验十三 CPU GPIO驱动程序设计...................................................9 3.实验十四中断实验...........................................................................10 4.实验十五数码管显示实验................................................................12 5.实验十六 LED点阵驱动程序设计...................................................19 6.实验十七 AD驱动实验....................................................................23 7.实验十八 DA驱动实验....................................................................26

六、实验中遇到的问题及解决方法........................................................30

七、实验总结及心得................................................................................31

一、实验目的

通过实验熟悉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)。

4)输入minicom然后回车,minicim设置为115200 8NI无流控。

5)打开PXA270_RP目标板电源,按目标板上的BOOT键,在minicom中应该会看到如下图:

6)在minicom终端窗口中,如图,输入下列四条命令 root ifconfig eth 192.168.0.50 up mount-o nolock 192.168.0.100:/ /mnt cd /mnt 此时,先将该窗口最小化,在后面的第 10 操作步骤中还将会回到该窗口中进行操作。

7)宿主机上打开一个终端窗口(Terminal),点击【红帽/System Tools/Terminal】启动终端窗口,输入下列 4 条命令: ① cd /home

②mkdir HW

③ cd HW

④ vi

HelloWorld.c

/*请您输入程序 7.1 程序清单*/

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

在 vi 里面先单击键盘 A 键,然后左下角会变成—INSER。输入程序的时候和其他编辑器是一样的,如下图。

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

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

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

9)重新打开第 7 步最小化的开有minicom的终端窗口,即到 PXA270-RP 目标板的mnt目录下,请您输入下列 3 条命令,运行HelloWorld编译成功的HelloWorld目标程序:

① cd home/HW

/*回到minicom中目标板的/mnt/home/HW目录下*/ ②ls ③./ HelloWorld

/*此时会看到如下图*/

四、驱动程序

1.设备驱动程序的概念

设备驱动程序实际是处理和操作硬件控制器的软件,从本质上讲,是内核中具有最高特权级的、驻留内存的、可共享的底层硬件处理例程。驱动程序是内核的一部分,是操作系统内核与硬件设备的直接接口,驱动程序屏蔽了硬件的细节,完成以下功能:

对设备初始化和释放;

对设备进行管理,包括实时参数设置,以及提供对设备的操作接口; 读取应用程序传送给设备文件的数据或者回送应用程序请求的数据; 检测和处理设备出现的错误。

Linux操作系统将所有的设备全部看成文件,并通过文件的操作界面进行操作。对用户程序而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口,一般来说,是把设备映射为一个特殊的设备文件,用户程序可以像对其他文件一样对此设备文件进行操作。这意味着:

由于每一个设备至少由文件系统的一个文件代表,因而都有一个“文件名”。应用程序通常可以通过系统调用open()打开设备文件,建立起与目标设备的连接。

打开了代表着目标设备的文件,即建立起与设备的连接后,可以通过read()、write()、ioctl()等常规的文件操作对目标设备进行操作。

设备文件的属性由三部分信息组成:第一部分是文件的类型,第二部分是一个主设备号,第三部分是一个次设备号。其中类型和主设备号结合在一起惟一地确定了设备文件驱动程序及其界面,而次设备号则说明目标设备是同类设备中的第几个。

由于Linux 中将设备当做文件处理,所以对设备进行操作的调用格式与对文件的操作类似,主要包括open()、read()、write()、ioctl()、close()等。应用程序发出系统调用命令后,会从用户态转到核心态,通过内核将open()这样的系统调用转换成对物理设备的操作。

2.驱动程序结构

一个设备驱动程序模块的基本框架

在系统内部,I/O设备的存取通过一组固定的入口点来进行,入口点也可以理解为设备的句柄,就是对设备进行操作的基本函数。字符型设备驱动程序提供如下几个入口点:

open入口点。打开设备准备I/O操作。对字符设备文件进行打开操作,都会调用设备的open入口点。open子程序必须对将要进行的I/O操作做好必要的准备工作,如清除缓冲区等。如果设备是独占的,即同一时刻只能有一个程序访问此设备,则open子程序必须设置一些标志以表示设备处于忙状态。

close入口点。关闭一个设备。当最后一次使用设备完成后,调用close子程序。独占设备必须标记设备方可再次使用。

read入口点。从设备上读数据。对于有缓冲区的I/O操作,一般是从缓冲区里读数据。对字符设备文件进行读操作将调用read子程序。

write入口点。往设备上写数据。对于有缓冲区的I/O操作,一般是把数据写入缓冲区里。对字符设备文件进行写操作将调用write子程序。

ioctl入口点。执行读、写之外的操作。

select入口点。检查设备,看数据是否可读或设备是否可用于写数据。select系统调用在检查与设备文件相关的文件描述符时使用select入口点。

3.设备注册和初始化

设备的驱动程序在加载的时候首先需要调用入口函数init_module(),该函数最重要的一个工作就是向内核注册该设备,对于字符设备调用register_chrdev()完成注册。register_chrdev的定义为:intregister_chrdev(unsigned int major, const char *name, struct file_ operations *fops);其中,major是为设备驱动程序向系统申请的主设备号,如果为0,则系统为此驱动程序动态分配一个主设备号。name是设备名,fops是对各个调用的入口点说明。此函数返回0时表示成功;返回-EINVAL,表示申请的主设备号非法,主要原因是主设备号大于系统所允许的最大设备号;返回-EBUSY,表示所申请的主设备号正在被其他设备程序使用。如果动态分配主设备号成功,此函数将返回所分配的主设备号。如果register_chrdev()操作成功,设备名就会出现在/proc/dvices文件中。

Linux在/dev目录中为每个设备建立一个文件,用ls–l命令列出函数返回值,若小于0,则表示注册失败;返回0或者大于0的值表示注册成功。注册以后,Linux将设备名与主、次设备号联系起来。当有对此设备名的访问时,Linux通过请求访问的设备名得到主、次设备号,然后把此访问分发到对应的设备驱动,设备驱动再根据次设备号调用不同的函数。

当设备驱动模块从Linux内核中卸载,对应的主设备号必须被释放。字符设备在cleanup_ module()函数中调用unregister_chrdev()来完成设备的注销。unregister_chrdev()的定义为:intunregister_chrdev(unsigned int major, const char *name);包括设备注册在内,设备驱动的初始化函数主要完成的功能是有以下5项。(1)对驱动程序管理的硬件进行必要的初始化。

对硬件寄存器进行设置。比如,设置中断掩码,设置串口的工作方式、并口的数据方向等。

(2)初始化设备驱动相关的参数。

一般说来,每个设备都要定义一个设备变量,用以保存设备相关的参数。在这一步骤里对设备变量中的项进行初始化。

(3)在内核注册设备。

调用register_chrdev()函数来注册设备。(4)注册中断。

如果设备需要IRQ支持,则要使用request_irq()函数注册中断。(5)其他初始化工作。

初始化部分一般还负责给设备驱动程序申请包括内存、时钟、I/O端口等在内的系统资源,这些资源也可以在open子程序或者其他地方申请。这些资源不用时,应该释放,以利于资源的共享。

若驱动程序是内核的一部分,初始化函数则要按如下方式声明: int __initchr_driver_init(void);其中__init是必不可少的,在系统启动时会由内核调用chr_driver_init,完成驱动程序的初始化。

当驱动程序是以模块的形式编写时,则要按照如下方式声明: intinit_module(void)当运行后面介绍的insmod命令插入模块时,会调用init_module函数完成初始化工作。

4.设备驱动程序的开发过程

由于嵌入式设备由于硬件种类非常丰富,在默认的内核发布版中不一定包括所有驱动程序。所以进行嵌入式Linux系统的开发,很大的工作量是为各种设备编写驱动程序。除非系统不使用操作系统,程序直接操纵硬件。嵌入式Linux系统驱动程序开发与普通Linux开发没有区别。可以在硬件生产厂家或者Internet上寻找驱动程序,也可以根据相近的硬件驱动程序来改写,这样可以加快开发速度。实现一个嵌入式Linux设备驱动的大致流程如下。

(1)查看原理图,理解设备的工作原理。一般嵌入式处理器的生产商提供参考电路,也可以根据需要自行设计。

(2

北邮电子院专业实验报告

第一篇:北邮电子院专业实验报告 电子工程学院 ASIC专业实验报告 班级: 姓名: 学号: 班内序号: ...
点击下载
分享:
最新文档
热门文章
    确认删除?
    QQ
    • QQ点击这里给我发消息
    微信客服
    • 微信客服
    回到顶部