<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://community.arm.com/utility/feedstylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Problem passing pointer argument to reentrant function</title><link>https://community.arm.com/developer/tools-software/tools/f/keil-forum/37153/problem-passing-pointer-argument-to-reentrant-function</link><description> 
Hi All, 

 
 TARGET 
I am using C51 tools to compile a simple app for an ST uPSD33xx. 

 
 OUTLINE 
The problem I am experiencing maifests itself as an incorrect value
in a pointer passed as an argument to a reentrant function. 

 
 DETAILS 
OK, I am</description><dc:language>en-US</dc:language><generator>Telligent Community 10</generator><item><title>RE: Problem passing pointer argument to reentrant function</title><link>https://community.arm.com/thread/112644?ContentTypeID=1</link><pubDate>Wed, 07 Feb 2007 15:05:48 GMT</pubDate><guid isPermaLink="false">dd9e70c8-6d3c-4c71-b136-2456382a7b5c:cc4e9973-df5c-43f5-9540-3fa7059f4da4</guid><dc:creator>Andy Atkinson</dc:creator><description>&lt;p&gt;&lt;p&gt;
Hi Jay,&lt;/p&gt;

&lt;p&gt;
Thanks for the advice.&lt;/p&gt;

&lt;p&gt;
Regards&lt;/p&gt;

&lt;p&gt;
Andy&lt;/p&gt;
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Problem passing pointer argument to reentrant function</title><link>https://community.arm.com/thread/98889?ContentTypeID=1</link><pubDate>Wed, 07 Feb 2007 08:08:35 GMT</pubDate><guid isPermaLink="false">dd9e70c8-6d3c-4c71-b136-2456382a7b5c:e0754295-9c54-4463-8176-2b5d5a7c39c2</guid><dc:creator>Jason Daniel</dc:creator><description>&lt;p&gt;&lt;p&gt;
Andy,&lt;/p&gt;

&lt;p&gt;
Just one more clarification: The stack used for reentrant
functions is distinct from the &amp;quot;actual&amp;quot; 8051 stack. Make sure you&amp;#39;re
checking the right stack status based on the memory model you&amp;#39;re
using. For details, take a look at reentrant functions in the
manual.&lt;/p&gt;
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Problem passing pointer argument to reentrant function</title><link>https://community.arm.com/thread/98888?ContentTypeID=1</link><pubDate>Wed, 07 Feb 2007 08:04:45 GMT</pubDate><guid isPermaLink="false">dd9e70c8-6d3c-4c71-b136-2456382a7b5c:ee8983b5-23fc-4984-9786-9cd5908892ba</guid><dc:creator>Jason Daniel</dc:creator><description>&lt;p&gt;&lt;p&gt;
Andy,&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;Regarding the functional calling from background and ISR -
what, specifically, is the problem(s) with this? I have seen nothing
in the Keil documentation to suggest that doing so in a &amp;#39;bad idea&amp;#39;.
In fact the tool chain supports directives to do just this
(NOAREGS/ARGES, reentrant, etc - section 8.4.2.5 of the C51 Primer).
Are you referring to the run-time overhead of making such a
call?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;
As Drew has already pointed out, my basic concern is with the cost
in terms of execution speed. My own tendencies lead toward
duplicating the code in the ISRs in order to avoid reentrant function
calls (and often to just avoid function calls at all). If the bit of
code is large enough that duplicating it in the ISRs is difficult in
terms of code size, then that&amp;#39;s probably an indication that it
doesn&amp;#39;t belong in the ISR itself, but in main code. Those things
notwithstanding, it&amp;#39;s not a hard-and-fast rule, but just a bit of
hard-earned advice I thought I&amp;#39;d pass along.&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;Regarding the &amp;#39;crazy value&amp;#39; is it either 0x0000 or 0xFFFF and
the data being pointed to is also not correct - all zeros - so
something is definitley not 100%. What common problems are there
regarding passing generic/memory-specific pointers to
functions?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;
This situation is indeed strange. Unless you&amp;#39;re missing something
very obvious in the code (which is unlikely in what you&amp;#39;ve posted),
you may be running up against the wall I call the &amp;quot;real-world.&amp;quot; The
fact that the call to a reentrant function isn&amp;#39;t going well leads me
to wonder about the state of the stack. When a function is tagged as
reentrant, the compiler does not generate code to pass parameters in
registers, but instead passes them on the stack. What is the value of
the stack pointer when you&amp;#39;re in the bad function call? One way to
quickly get a feel for your stack usage is to initialize it all to
some known value (like ascii &amp;#39;X&amp;#39;) at startup, then look at it when
your program is running. If there are no &amp;#39;X&amp;#39;s left, you know you&amp;#39;re
at least perilously close to a stack overflow. Give that a try and
let us know the results.&lt;/p&gt;

&lt;p&gt;
-Jay Daniel&lt;/p&gt;
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Problem passing pointer argument to reentrant function</title><link>https://community.arm.com/thread/98892?ContentTypeID=1</link><pubDate>Tue, 06 Feb 2007 20:11:38 GMT</pubDate><guid isPermaLink="false">dd9e70c8-6d3c-4c71-b136-2456382a7b5c:7ef4a88b-2808-420b-a693-be93863fd279</guid><dc:creator>Drew Davis</dc:creator><description>&lt;p&gt;&lt;p&gt;
As you say, it&amp;#39;s an efficiency concern.&lt;/p&gt;

&lt;p&gt;
The 8051 architecture is poorly suited to maintaining a stack. It
just doesn&amp;#39;t have many pointer registers or good indexed addressing
modes to take advantage of them if it did. So, the Keil compiler does
some fairly clever compile-time analysis to assign parameters and
locals to fixed memory locations. The code generator can then
generate direct access to the data. The compiler and linker analyze
the call tree to know which functions cannot be active at the same
time, and thus which memory can be reused in different functions.&lt;/p&gt;

&lt;p&gt;
For this purpose, every context is a different call tree. main()
has one call tree, and each ISR has a different one. A function
shared between main and an ISR, or two ISRs, can&amp;#39;t participate in the
overlay scheme, because you might be in both copies of the function
at once.&lt;/p&gt;

&lt;p&gt;
To avoid this problem, you need to make the functions reentrant.
As you note, there are special Keil keywords just for this. However,
this means that the code generator starts putting all those parametes
and locals on a &amp;quot;software stack&amp;quot;, maintaining a stack pointer and
dragging the data back and forth through the DPTR. The tools make the
C pretty painless, but you execute many (many) more instructions and
generate larger code for the convenience.&lt;/p&gt;

&lt;p&gt;
Some people thus prefer to duplicate functions for ISRs. Usually
the idea is to make the ISR faster, but sometimes it might even be
smaller code once you eliminate all the stack simulation
overhead.&lt;/p&gt;

&lt;p&gt;
It&amp;#39;s not always a bad idea to make functions reentrant and share
them, but true reentrancy is expensive enough on an 8051 that it&amp;#39;s
worth thinking about.&lt;/p&gt;
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Problem passing pointer argument to reentrant function</title><link>https://community.arm.com/thread/74798?ContentTypeID=1</link><pubDate>Tue, 06 Feb 2007 18:01:19 GMT</pubDate><guid isPermaLink="false">dd9e70c8-6d3c-4c71-b136-2456382a7b5c:32ebba65-dbe9-4877-a9b3-27586339e3b0</guid><dc:creator>Andy Atkinson</dc:creator><description>&lt;p&gt;&lt;p&gt;
Hi Jay,&lt;/p&gt;

&lt;p&gt;
Regarding the functional calling from background and ISR - what,
specifically, is the problem(s) with this? I have seen nothing in the
Keil documentation to suggest that doing so in a &amp;#39;bad idea&amp;#39;. In fact
the tool chain supports directives to do just this (NOAREGS/ARGES,
reentrant, etc - section 8.4.2.5 of the C51 Primer). Are you
referring to the run-time overhead of making such a call?&lt;/p&gt;

&lt;p&gt;
So if I have 2 serial ports, so 2 ISRs, and the serial driver is
based on a ringbuffer, surely you either have to make a function call
to the common ringbuffer code or duplicate the code in each ISR.&lt;/p&gt;

&lt;p&gt;
Do you use a different strategy for tackling such a situatuon?
Does this come down to a &amp;#39;code size vs execution speed&amp;#39; trade-off or
are you concious of more fundamental issues with this type of basic
design problem?&lt;/p&gt;

&lt;p&gt;
Regarding the &amp;#39;crazy value&amp;#39; is it either 0x0000 or 0xFFFF and the
data being pointed to is also not correct - all zeros - so something
is definitley not 100%. What common problems are there regarding
passing generic/memory-specific pointers to functions? I would have
thought that this is a bread-n-butter (basic!) activity.
Incidentally, making the pointers memory-specific made no difference,
but I take on-board the benefits of using this type of pointer
regarding code size and execution speed. Thanks.&lt;/p&gt;

&lt;p&gt;
I have moved the code from sendByte to &amp;#39;inline&amp;#39; and all is well,
but it does not explain what was going wrong (and result is some
duplication of code!).&lt;/p&gt;

&lt;p&gt;
Cheers&lt;/p&gt;

&lt;p&gt;
Andy&lt;/p&gt;
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Problem passing pointer argument to reentrant function</title><link>https://community.arm.com/thread/47757?ContentTypeID=1</link><pubDate>Tue, 06 Feb 2007 09:35:29 GMT</pubDate><guid isPermaLink="false">dd9e70c8-6d3c-4c71-b136-2456382a7b5c:ddcd8723-bf4a-4d3b-951b-a203adc7d497</guid><dc:creator>Jason Daniel</dc:creator><description>&lt;p&gt;&lt;p&gt;
Andy,&lt;/p&gt;

&lt;p&gt;
Let me just get this one bit of advice out of the way before
someone else does in a less gentle manner: Making function calls from
ISRs is generally a bad idea (ie. calling sendByte from within the
ISR as well as main code).&lt;/p&gt;

&lt;p&gt;
Also, what do you mean by pChannel having a &amp;quot;crazy value?&amp;quot; What is
the value before the call and then inside the function? Remember that
when you use a function declaration like:&lt;/p&gt;

&lt;pre&gt;
static uint16 _writeSerial (char* buffer, uint16 numBytes, SERIAL_CHANNEL_T *pChannel);
&lt;/pre&gt;

&lt;p&gt;
both buffer and pChannel will be 3-byte values. This is because
you&amp;#39;ve made them &amp;quot;generic pointers&amp;quot; by not explicitly specifying
which memory area they reside in. The first (highest-order) byte of
the pointer will contain the memory area, while the lower two bytes
should be what you expect in a &amp;quot;normal&amp;quot; pointer.&lt;/p&gt;
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>