⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter 7 pointers -- valvano.htm

📁 介绍了在嵌入式系统中如何用c来设计嵌入式软件
💻 HTM
📖 第 1 页 / 共 3 页
字号:
however, need not observe this restriction, since they make no assumption about 
the relative positions of objects. For example if <B>pt1</B> points into one 
data array and <B>pt2</B> points into a different array, then comparing 
<B>pt1</B> to <B>pt2</B> would be meaningless. Which pointer is larger would 
depend on where in memory the two arrays were assigned.</FONT></P>
<P><B><I><FONT face=Helvetica,Arial><A name=FIFO></A>A FIFO Queue 
Example</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">To illustrate the use of pointers we will 
design a two-pointer FIFO. The first in first out circular queue (FIFO) is also 
useful for data flow problems. It is a very common data structure used for I/O 
interfacing. The order preserving data structure temporarily saves data created 
by the source (producer) before it is processed by the sink (consumer). The 
class of FIFO&#8217;s studied in this section will be statically allocated global 
structures. Because they are global variables, it means they will exist 
permanently and can be shared by more than one program. The advantage of using a 
FIFO structure for a data flow problem is that we can decouple the source and 
sink processes. Without the FIFO we would have to produce 1 piece of data, then 
process it, produce another piece of data, then process it. With the FIFO, the 
source process can continue to produce data without having to wait for the sink 
to finish processing the previous data. This decoupling can significantly 
improve system performance. </FONT></P>
<P><FONT face="Times New Roman,Times" size=2>GETPT</FONT><FONT 
face="Times New Roman,Times"> points to the data that will be removed by the 
next call to GET, and </FONT><FONT face="Times New Roman,Times" size=2>PUTPT 
</FONT><FONT face="Times New Roman,Times">points to the empty space where the 
data will stored by the next call to PUT. If the FIFO is full when PUT is called 
then the subroutine should return a full error (e.g., V=1.) Similarly, if the 
FIFO is empty when GET is called, then the subroutine should return an empty 
error (e.g., V=1.) The </FONT><FONT face="Times New Roman,Times" 
size=2>PUTPT</FONT><FONT face="Times New Roman,Times"> and </FONT><FONT 
face="Times New Roman,Times" size=2>GETPT</FONT><FONT 
face="Times New Roman,Times"> must be wrapped back up to the top when they reach 
the bottom. </FONT></P>
<P>&nbsp;</P>
<P><IMG height=161 src="Chapter 7 Pointers -- Valvano.files/fifo.gif" 
width=361></P>
<ADDRESS><FONT face="Times New Roman,Times">Figure 7-3: Fifo example showing the 
PUTPT and GETPT wrap. </FONT></ADDRESS>
<P>&nbsp;</P>
<P><FONT face="Times New Roman,Times">There are two mechanisms to determine 
whether the FIFO is empty or full. A simple method is to implement a counter 
containing the number of bytes currently stored in the FIFO. GET would decrement 
the counter and PUT would increment the counter. The second method is to prevent 
the FIFO from being completely full. For example, if the FIFO had 100 bytes 
allocated, then the PUT subroutine would allow a maximum of 99 bytes to be 
stored. If there were already 99 bytes in the FIFO and another PUT were called, 
then the FIFO would not be modified and a full error would be returned. In this 
way if PUTPT equals GETPT at the beginning of GET, then the FIFO is empty. 
Similarly, if PUTPT+1 equals GETPT at the beginning of PUT, then the FIFO is 
full. Be careful to wrap the PUTPT+1 before comparing it to GETPT. This second 
method does not require the length to be stored or calculated.</FONT></P>
<DIR>
<P><CODE>/* Pointer implementation of the FIFO */<BR>#define FifoSize 10 /* 
Number of 8 bit data in the Fifo */<BR>#define START_CRITICAL() asm(" tpa\n staa 
%SaveSP\n sei")<BR>#define END_CRITICAL() asm( ldaa %SaveSP\n tap")<BR>char 
*PUTPT;&nbsp;&nbsp;&nbsp;&nbsp;/* Pointer of where to put next */<BR>char 
*GETPT;&nbsp;&nbsp;&nbsp;&nbsp;/* Pointer of where to get next */<BR>/* FIFO is 
empty if PUTPT=GETPT */<BR>/* FIFO is full if PUTPT+1=GETPT */<BR>char 
Fifo[FifoSize]; /* The statically allocated fifo data */<BR>void InitFifo(void) 
{unsigned char SaveSP;<BR>&nbsp;&nbsp;&nbsp;&nbsp;START_CRITICAL(); /* make 
atomic, entering critical section 
*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;PUTPT=GETPT=&amp;Fifo[0]; /* Empty when 
PUTPT=GETPT */<BR>&nbsp;&nbsp;&nbsp;&nbsp;END_CRITICAL(); /* end critical 
section */<BR>}<BR>int PutFifo (char data) { char *Ppt; /* Temporary put pointer 
*/<B><BR></B>unsigned char SaveSP;<BR>&nbsp;&nbsp;&nbsp;&nbsp;START_CRITICAL(); 
/* make atomic, entering critical section 
*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;Ppt=PUTPT; /* Copy of put pointer 
*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;*(Ppt++)=data; /* Try to put data into fifo 
*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;if (Ppt == &amp;Fifo[FifoSize]) Ppt = 
&amp;Fifo[0]; /* Wrap */<BR>&nbsp;&nbsp;&nbsp;&nbsp;if (Ppt == GETPT ){ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END_CRITICAL();&nbsp;&nbsp;/* 
end critical section 
*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(0);}&nbsp;&nbsp;&nbsp;/* 
Failed, fifo was full */<BR>&nbsp;&nbsp;&nbsp;&nbsp;else{ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PUTPT=Ppt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END_CRITICAL();&nbsp;&nbsp;/* 
end critical section 
*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(-1);&nbsp;&nbsp;&nbsp;/* 
Successful */ <BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}<BR>int GetFifo (char *datapt) 
{unsigned char SaveSP;<BR>&nbsp;&nbsp;&nbsp;&nbsp;if (PUTPT== GETPT){ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(0);}&nbsp;&nbsp;&nbsp;/* 
Empty if PUTPT=GETPT */<BR>&nbsp;&nbsp;&nbsp;&nbsp;else{ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;START_CRITICAL(); /* make 
atomic, entering critical section 
*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*datapt=*(GETPT++);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if 
(GETPT == 
&amp;Fifo[FifoSize])<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GETPT 
= 
&amp;Fifo[0];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END_CRITICAL(); 
&nbsp;/* end critical section 
*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(-1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}</CODE></P></DIR>
<ADDRESS><FONT face="Times New Roman,Times">Listing 7-3: Fifo queue implemented 
with pointers</FONT></ADDRESS>
<P>The START_CRITICAL and END_CRITICAL macros are specific to ICC11/ICC12, 
otherwise this example will operate using Hiware.</P>
<P><FONT face="Times New Roman,Times">Since these routines have read modify 
write accesses to global variables the three functions (InitFifo, PutFifo, 
GetFifo) are themselves not reentrant. Consequently interrupts are temporarily 
disabled, to prevent one thread from reentering these Fifo functions. One 
advantage of this pointer implementation is that if you have a single thread 
that calls the GetFifo (e.g., the main program) and a single thread that calls 
the PutFifo (e.g., the serial port receive interrupt handler), then this PutFifo 
function can interrupt this GetFifo function without loss of data. So in this 
particular situation, interrupts would not have to be disabled. It would also 
operate properly if there were a single interrupt thread calling GetFifo (e.g., 
the serial port transmit interrupt handler) and a single thread calling PutFifo 
(e.g., the main program.) On the other hand, if the situation is more general, 
and multiple threads could call PutFifo or multiple threads could call GetFifo, 
then the interrupts would have to be temporarily disabled as shown.</FONT></P>
<P><B><I><FONT face=Helvetica,Arial><A name=IO></A>I/O Port 
Access</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">Even though the mechanism to access I/O 
ports technically does not fit the definition of pointer, it is included in this 
chapter because it involves addresses. The format used by both the Imagecraft 
and Hiware compilers fits the following model. The following listing shows one 
8-bit and two 16-bit 6811 I/O ports. The line TFLG1=0x08; generates an 8-bit I/O 
write operation to the port at address 0x1023. The TCNT on the right hand side 
of the assignment statement generates a 16-bit I/O read operation from the port 
at address 0x100E. The TOC5 on the left hand side of the assignment statement 
generates a 16-bit I/O write operation from the port at address 0x101E. The 
TFLG1 inside the while loop generates repeated 8-bit I/O read operations until 
bit 3 is set.</FONT></P>
<DIR>
<P><CODE>#define TFLG1 *(unsigned char volatile *)(0x1023)<BR>#define TCNT 
*(unsigned short volatile *)(0x100E)<BR>#define </CODE><FONT face=Courier 
size=2>TOC5 </FONT><CODE>*(unsigned short volatile *)(0x101E)<BR>void 
wait(unsigned int delay){<BR>&nbsp;&nbsp;&nbsp;TFLG1=0x08; /* clear OC5F 
*/<BR>&nbsp;&nbsp;&nbsp;TOC5=TCNT+delay; /* TCNT at end of wait 
*/<BR>&nbsp;&nbsp;&nbsp;while((TFLG1&amp;0x08)==0){}; /* wait for 
OC5F*/<BR></CODE><FONT face=Courier size=2>}</FONT></P></DIR>
<P><I>Listing 7-4: Sample ICC11/Hiware Program that accesses I/O ports</I></P>
<P><FONT face="Times New Roman,Times">A similar 6812 program is shown 
below.</FONT></P>
<DIR>
<P><CODE>#define TFLG1 *(unsigned char volatile *)(0x008E)<BR>#define TCNT 
*(unsigned short volatile *)(0x0084)<BR>#define </CODE><FONT face=Courier 
size=2>TC5 </FONT><CODE>*(unsigned short volatile *)(0x009A)<BR>void 
wait(unsigned int delay){<BR>&nbsp;&nbsp;&nbsp;TFLG1=0x20; /* clear C5F 
*/<BR>&nbsp;&nbsp;&nbsp;TC5=TCNT+delay; /* TCNT at end of wait 
*/<BR>&nbsp;&nbsp;&nbsp;while((TFLG1&amp;0x20)==0){}; /* wait for 
C5F*/<BR></CODE><FONT face=Courier size=2>}</FONT></P></DIR>
<P><I>Listing 7-5: Sample ICC12/Hiware Program that accesses I/O ports</I></P>
<P><FONT face="Times New Roman,Times">It was mentioned earlier that the volatile 
modifier will prevent the compiler from optimizing I/O programs. I.e., these 
examples would not work if the compiler read TFLG1 once, the used the same data 
over and over inside the while loop.</FONT></P>
<P><FONT face="Times New Roman,Times">To understand this syntax we break it into 
parts. Starting on the right is the absolute address of the I/O port. For 
example the 6811 TFLG1 register is at location 0x1023. The parentheses are 
necessary because the definition might be used in an arithmetic calculation. For 
example the following two lines are quite different:</FONT></P>
<P><CODE>&nbsp;&nbsp;&nbsp;TheTime=*(unsigned char volatile 
*)(0x1023)+100;<BR>&nbsp;&nbsp;&nbsp;TheTime=*(unsigned char volatile 
*)0x1023+100;</CODE></P>
<P><FONT face="Times New Roman,Times">In the second (incorrect) case the 
addition 0x01023+100 is performed on the address, not the data. The next part of 
the definition is a type casting. C allows you to change the type of an 
expression. For example (unsigned char volatile *) specifies that 0x1023 is an 
address that points at an 8-bit unsigned char. The * at the beginning of the 
definition causes the data to be fetched from the I/O port if the expression 
exists on the right-hand side of an assignment statement. The * also causes the 
data to be stored at the I/O port if the expression in on the left-hand side of 
the assignment statement. In this last way, I/O port accesses are indeed similar 
to pointers. For example the above example could have be implemented 
as:</FONT></P>
<DIR>
<P><CODE>unsigned char volatile *pTFLG1;<BR>unsigned short volatile 
*pTCNT;<BR>unsigned short volatile *p</CODE><FONT face=Courier 
size=2>TC5</FONT><CODE>;<BR>void wait(unsigned int 
delay){<BR>&nbsp;&nbsp;&nbsp;pTFLG1=(unsigned char volatile 
*)(0x008E);<BR>&nbsp;&nbsp;&nbsp;pTCNT=(unsigned short volatile 
*)(0x0084);<BR>&nbsp;&nbsp;&nbsp;p</CODE><FONT face=Courier 
size=2>TC5</FONT><CODE>=(unsigned short volatile 
*)(0x009A);<BR>&nbsp;&nbsp;&nbsp;(*pTFLG1)=0x20; 
<BR>&nbsp;&nbsp;&nbsp;(*pTC5)=(*pTCNT)+delay; 
<BR>&nbsp;&nbsp;&nbsp;while(((*pTFLG1)&amp;0x20)==0){}; <BR></CODE><FONT 
face=Courier size=2>}</FONT></P></DIR>
<P><I>Listing 7-6: ICC12/Hiware Program that accesses I/O ports using 
pointers</I></P>
<P><FONT face="Times New Roman,Times">This function first sets the three I/O 
pointers then accesses the I/O ports indirectly through the pointers.</FONT></P>
<P>&nbsp;</P>
<P><FONT face="Times New Roman,Times">Go to <A 
href="http://www.ece.utexas.edu/~valvano/embed/chap8/chap8.htm">Chapter 8 on 
Arrays and Strings</A> Return to <A 
href="http://www.ece.utexas.edu/~valvano/embed/toc1.htm">Table of Contents</A> 
</FONT></P>
<P>&nbsp;</P></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -