嵌入式C语言编程小知识

来源:互联网 发布:淘宝店主寄语 文艺 编辑:程序博客网 时间:2024/06/07 20:19

1.   

流水线被指令填满时才能发挥最大效能,即每时钟周期完成一条指令的执行(仅指单周期指令)。如果程序发生跳转,流水线会被清空,这将需要几个时钟才能使流水线再次填满。因此,尽量少的使用跳转指令可以提高程序执行效率,解决发案就是尽量使用指令的“条件执行”功能。


2.   

数组指针(类似于函数指针)

1>int  (*p)[4]

表示*p有4个元素,每个元素为整型。也就是p所指的对象有4个整型元素的数组,既P是行指针。

2> 指针数组(类似于指针函数)

  一个数组,其元素均为指针类型数据,称为指针数组;即指针数组中的每一个元素都相当于一个指针变量。

  一维指针数组的定义形式为:

类型名  *数组名[数组长度]

eg:int  *p[4]:

作用:它用于指向若干个字符串,使字符串处理更加方便灵活。适用于一个二维字符串数组,其中每一行的字符数组的长度各不相同

eg:char * name[]={“Follow me”,”BASIC”,”GreatWall”};


3.

 结构体

1>   可以用结构体变量做实参。但是用结构体变量作实参时,采取的是“值传递”的方式,将结构体变量所占的内存单元的内容全部顺序递给形参。形参也必须是同类型的结构体变量。

eg:pint(su);//注在此处su为结构体

注:这种传递方式在空间和时间上开销较大,如果结构体的规模较大时,开销是很可观的。

2>   用直向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参

eg:print(&su);//注在此处su为结构体


4.

 CPU字长与存储器位宽不一致处理   (32位CPU字长为4字节,存储器位宽一般为4字节对齐(32位地址总线))

例如:使用共用体来解决这一冲突:

union send_temp{

                             uint16 words;

                              uint8 bytes[2];

                             }send_buff;

eg:send_buff.bytes[0]=a;//此处a 是8位

  send_buff.bytes[1]=b;//此处 b 是8位;

此时就将8位字拼成了16位字存储了。

发送时send(send_buff.words)就可以每次发送一个16位的数据了。

CPU位数有两种不同的定义方式:有用CPU核心中通用寄存器的位宽定义的.也有用数据总线位宽定义

后一种定义方式确实就等于是用于传递数据的引脚的数量.不过大多数人更倾向于用前一种定义

假设用后一种定义方式.那么早在Pentium Pro / Ⅱ / Ⅲ 时代.
就已经使用64位数据总线了.但是大多数人不认为它们是 64 位CPU.
(64位浮点寄存器.32位通用寄存器.36位地址总线.64位数据总线.) 
我们更倾向于认为只有使用 64位通用寄存器的CPU才是真正的 64位.
而前面说的那种64位数据线.32位通用寄存器的CPU只能算是 32位的

寄存器的位数.其实就是说一个寄存器包含多少个二进制基本单元.32位寄存器就是由32个基本单元组成的.每个单元只能记录两种状态:0或1


5.

一个常见的调试策略是把一些printf函数的调用散布于程序中,确定错误出现的具体位置。但是,这些函数调用的输出结果被写入到缓冲区中,并不立即显示于屏幕上。事实上,如果程序失败,缓冲输去可能不会被实际写入(如_exit(1)),因此得到的错误位置就是错误的。解决的方法是在每个用于调试的printf函数之后立即调用fflush函数即可得到。

printf(“something  or other”);

fflush(stdout);


6.

14.关键字volatile的用法

volatile变量可能用于如下几种情况:

1>设备的硬件寄存器(如:状态寄存器)

2>一个中断服务子程序中会访问到的全局变量

3>多线程应用中被几个任务共享的变量


7.

关键字register的用法:

当对一个变量频繁被读写时,需要反复访问内存,从而花费大量的存取时间。为此,C语言提供了一种变量,即寄存器变量。这种变量存放在CPU的寄存器中,使用时,不需要访问内存,而直接从寄存器中读写,从而提高效率。寄存器变量的说明符是register。对于循环次数较多的循环控制变量及循环体内反复使用的变量均可定义为寄存器变量,而循环计数是应用寄存器变量的最好候选者。
(1) 只有局部自动变量和形参才可以定义为寄存器变量因为寄存器变量属于动态存储方式,凡需要采用静态存储方式的量都不能定义为寄存器变量,包括:模块间全局变量、模块内全局变量、局部static变量;
(2) register是一个"建议"型关键字,意指程序建议该变量放在寄存器中,但最终该变量可能因为条件不满足并未成为寄存器变量,而是被放在了存储器中,但编译器中并不报错(在C++语言中有另一个"建议"型关键字:inline)。


8.

对于程序代码,已经被烧录在FLASH或ROM中,我们可以让CPU直接从其中读取代码执行,但通常这不是一个好办法,我们最好在系统启动后将FLASH或ROM中的目标代码拷贝入RAM中后再执行以提高取指令速度

CPU对各种存储器的访问速度,基本上是:

CPU内部RAM > 外部同步RAM > 外部异步RAM > FLASH/ROM


9.

宏定义 副作用:

#include <stdio.h>
#define MIN(x,y) ((x) <= (y) ? (x):(y))
int main ()
{
    int i = 10;
    int a[5] = {9,12,11,10,13};
    int *p = a;
    int j;
    
    j = MIN(*p++, i);       输出:j=12
    printf("%d\n", j);
     printf("%d\n", *p);    输出11
    return (0);
}

首先 *p(此时*p = 9)与i比较,之后自加1,此时*p = 12;

比较发现9 < 10 取(*p++)的值  先取*p =12   p再自自加1   最后输出*p为11


因此不要给宏定义传入有副作用的"参数"。


指令周期指令周期是执行一条指令所需要的时间,一般由若干个机器周期组成,是从取指令、分析指令到执行完所需的全部时间。


CPU周期 又称机器周期,CPU访问一次内存所花的时间较长,因此用从内存读取一条指令字的最短时间来定义。

在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶段,每一阶段完成一项工作。例如,取指令、存储器读、存储器写等

时钟周期 通常称为节拍脉冲或T周期。一个CPU周期包含若干个时钟周期。

时钟周期也称为振荡周期,定义为时钟脉冲的倒数(可以这样来理解,时钟周期就是单片机外接晶振的倒数,例如12M的晶振,它的时间周期就是1/12 us),计算机中最基本的、最小的时间单位,对同一种机型的计算 机,时钟频率越高,计算机的工作速度就越快。

总线周期:

    由于存贮器和I/O端口是挂接在总线上的,CPU对存贮器和I/O接口的访问,是通过总线实现的。通常把CPU通过总线对微处理器外部(存贮器或 I/O接口)进行一次访问所需时间称为一个总线周期。


CLA是一条非访内指令,它需要两个CPU 周期,其中取指令阶段需要一个CPU周期,执行指令阶段需要一个CPU周期。
1、取指令阶段
(1)程序计数器PC的内容20(八进制)被装入地址寄存器AR;
(2)程序计数器内容加1,变成21,为取下一条指令做好准备;
(3)地址寄存器的内容被放到地址总线上;
(4)所选存储器单元20的内容经过数据总线,传送到数据缓冲寄存器DR;
(5)缓冲寄存器的内容传送到指令寄存器IR
(6)指令寄存器中的操作码被译码或测试
(7)CPU识别出是指令CLA,至此,取指令阶段即告结束。
2、执行指令阶段
(1)操作控制器送一控制信号给算术逻辑运算单元ALU;
(2)ALU响应该控制信号,将累加寄存器AC的内容全部清零,从而执行了CLA指令(结果放回累加器,替换、其原来的数)

指令不同,所需的机器周期数也不同。对于一些简单的的单字节指令,在取指令周期中,指令取出到指令寄存器后,立即译码执行,不再需要其它的机器周期。对于一些比较复杂的指令,例如转移指令、乘法指令,则需要两个或者两个以上的机器周期。[3]
从指令的执行速度看,单字节和双字节指令一般为单机器周期双机器周期三字节指令都是双机器周期,只有乘、除指令占用4个机器周期
因此在进行编程时,在完成相同工作的情况下,选用占用机器周期少的命令会提高程序的执行速率,尤其是在编写大型程序程序的时候,其效果更加明显


cpu流水线:
cpu流水线技术是一种将指令分解为多步,并让不同指令的各步操作重叠,从而实现几条指令并行处理,以加速程序运行过程的技术。指令的每步有各自独立的电路来处理,每完成一步,就进到下一步,而前一步则处理后续指令。采用流水线技术后,并没有加速单条指令的执行,每条指令的操作步骤一个也不能少,只是多条指令的不同操作步骤同时执行,因而从总体上看加快了指令流速度,缩短了程序执行时间
为了进一步满足普通流水线设计所不能适应的更高时钟频率的要求,高档位处理器中的流水线的深度(级数)在逐代增多。流水线级数越多,每级所花的时间越短,时钟周期就可以设计的越短,指令速度越快,指令平均执行时间也就越短。
流水线技术是通过增加计算机硬件来实现的。它要求各功能段能互相独立地工作,这就要增加硬件,相应地也加大了控制的复杂性。如果没有互相独立的操作部件,很可能会发生各种冲突。例如要能预取指令,就需增加指令的硬件电路,并把取来的指令存放到指令队列缓冲器中,使微处理器能同时进行取指令和分析、执行指令的操作。








原创粉丝点击