这一节,我们针对大家提出的有关定义寄存器
结构体的问题进行解析。在NIOS II软件开发过程中,如果使用我们提出的寄存器操作方式的话,首先需要定义一个寄存器结构体,之所以这样做是为了在软件书写过程中操作方便,更是为了增强程序的可读性。我们就拿UART来举例说明。
首先,我们看一下UART的寄存器说明,如下表所示
![](../img/eep/emb/emb-703362oznwcht2oc.jpg)
我们通过上表可以看到,UART包括6个寄存器(由于最后一个寄存器一般不用,所以建立的结构体中没有加入它),假设基地址为0x00的话,那么他们的地址分别为0x00,0x01,0x02,0x03,0x04,0x05。也就是说,各个寄存器之间是存在顺序的。那么,在我们建立结构体过程中也要注意他们的顺序问题。建立的结构体如下所示
view sourceprint?
04 | volatile unsigned long int RECEIVE_DATA :8; |
05 | volatile unsigned long int NC :24; |
07 | volatile unsigned long int WORD; |
12 | volatile unsigned long int TRANSMIT_DATA :8; |
13 | volatile unsigned long int NC :24; |
15 | volatile unsigned long int WORD; |
20 | volatile unsigned long int PE :1; |
21 | volatile unsigned long int FE :1; |
22 | volatile unsigned long int BRK :1; |
23 | volatile unsigned long int ROE :1; |
24 | volatile unsigned long int TOE :1; |
25 | volatile unsigned long int TMT :1; |
26 | volatile unsigned long int TRDY :1; |
27 | volatile unsigned long int RRDY :1; |
28 | volatile unsigned long int E :1; |
29 | volatile unsigned long int NC :1; |
30 | volatile unsigned long int DCTS :1; |
31 | volatile unsigned long int CTS :1; |
32 | volatile unsigned long int EOP :1; |
33 | volatile unsigned long int NC1 :19; |
35 | volatile unsigned long int WORD; |
40 | volatile unsigned long int IPE :1; |
41 | volatile unsigned long int IFE :1; |
42 | volatile unsigned long int IBRK :1; |
43 | volatile unsigned long int IROE :1; |
44 | volatile unsigned long int ITOE :1; |
45 | volatile unsigned long int ITMT :1; |
46 | volatile unsigned long int ITRDY :1; |
47 | volatile unsigned long int IRRDY :1; |
48 | volatile unsigned long int IE :1; |
49 | volatile unsigned long int TRBK :1; |
50 | volatile unsigned long int IDCTS :1; |
51 | volatile unsigned long int RTS :1; |
52 | volatile unsigned long int IEOP :1; |
53 | volatile unsigned long int NC :19; |
55 | volatile unsigned long int WORD; |
60 | volatile unsigned long int BAUD_RATE_divISOR :16; |
61 | volatile unsigned long int NC :16; |
63 | volatile unsigned long int WORD; |
对于这样一个大的结构体,我们来逐层分析一下:
第一, 整个结构体由5个共用体组成,共同体的顺序是由寄存器的偏移量决定的,这一点前面已经有所叙述。
第二, 每个共用体由一个结构体和一个volatile unsigned long int型的变量组成。
第三, 共用体中的结构体由位域构成,位域中的内容也是存在顺序的,这个顺序是由寄存器的结构决定,而且是由低到高排列。其中,NC表示该位为空位或保留,不能对其进行操作。
通过大家的反馈,除了语法问题以外,有两个问题需要说明一下:
1. 为什么里面的变量都定义成unsignedlongint?
首先需要说明一点,在NIOS II中,unsignedlongint是32位,跟unsignedint是一样的,unsignedlonglongint才是64位的。
有人会问,在寄存器的表格中,寄存器的位数是0到15的,也就是16位,那你为什么定义成32位的呢?其实,这个问题涉及到了NIOS II的地址对齐问题,它是属于硬件构架的范畴。
当系统中存在数据宽度不匹配的主从端口时就要考虑地址对齐的问题。地址对齐分为两类,一类是静态地址对齐,另一类就是动态地址对齐。一般来说存储器外设使用动态地址对齐,而寄存器外设使用静态地址对齐,之所以是这样,是由动态地址对齐和静态地址对齐的特点决定的,在静态地址对齐方式下,主端单次传输对应从端口的一次传输,而在动态地址对齐方式下,一个主端口读传输,则要引起多次从端口读传输。想要更加具体的了解他们特点的,大家自行查找吧,我在这里就不详细叙述了。
我们要将寄存器定义为unsignedlongint类型,就跟这个静态地址对齐有关系了。现在我们是UART端口16位,而NIOS II主端口32位的情况,在这种情况下,NIO