Re-entrant functions help required

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Hi All,

I would like some of my XMC4500 functions to be re-entrant. They will be called from the main program and 2 interrupt levels. Can anyone point me in to some documentation on how to do this please ?

Thank you very much
Best regards
Aaron
0 Likes
7 Replies
User5581
Level 3
Level 3
So far I've had luck with this approach: Use stack automatic storage for all function local variables to make that function re-entrant. Any non-automatic shared memory accessed by both main loop and ISR callbacks should either be atomic or protected by a synchronization mechanism.

This synchronization mechanism seemed to work for me in an ADC ISR callback. After calling ADC001_GetResult(), I take care to write the conversion results and a timestamp atomically into the structure pointed to by p.

(I'm not using an RTOS here. If I were, I'd use the semaphores and mutexes supplied by the RTOS instead.)
		
typedef struct {
uint32_t time; /**< time of the ADC ISR Callback (Aligned on 32 bit boundary) in milliseconds */
uint16_t rawRd; /**< raw ADC results (Aligned on 32 bit boundary) */
uint8_t semaphore; /**< Lock bit for Cortex M3/M4 LDREX/STREX exclusive access action */
} __attribute__ ((aligned (4))) AD_Results_Type;


In the ISR:
	
AD_Results_Type * p;

uint8_t * p_lock_bit = &(p->semaphore); // points to semaphore-like synchronization byte
// Cortex-M4 so called 'Exclusive Action':
// If the main thread (or another interrupt?) has already grabbed the semaphore
// then don't alter the conversion data in p->
if(__LDREXB( p_lock_bit)==0) // if lock bit is not claimed
{
if (__STREXB(1,p_lock_bit) == 0) // try to claim it.
{ // If the semaphore was claimed safely then
// access to different fields of p-> can now be done atomically:
p->time = now;
p->rawRd = Result.Result;
*p_lock_bit = 0; // release the semaphore
}
}


Code called from the main loop (non-ISR) that atomically gets the conversion and timestamp for export:

uint8_t * p_lock_bit = &(p->semaphore); // points to semaphore

// Cortex-M4 so called 'Exclusive Action':
if(__LDREXB( p_lock_bit)==0) // if lock bit is not claimed
{
if (__STREXB(1,p_lock_bit) == 0) // try to claim it.
{ // If the semaphore was claimed safely then
// access to different fields of p-> can now be done atomically:
if (ADC_ResultNotAvailable(p))
{
*p_lock_bit = 0; // release the semaphore if we grabbed it
return ADC_NoAvailableReading_Error;
}
if (Counts)
*Counts = p->rawRd;
if (ptime)
*ptime = p->time;
*p_lock_bit = 0; // release the semaphore if we grabbed it
break;
}
}
0 Likes
Not applicable
For the XC800 you use the keyword reentrant and the compiler switches to using stack pushing for that function. It's pretty straightforward and simple:


void foo() reentrant {

}


I'd be surprised if there wasn't a similar mechanism for your platform.
0 Likes
Not applicable
Hi Zoompig,

Thank you very much for taking the time to reply and for your examples. Much appreciated.

Best regards
Aaron
0 Likes
Not applicable
Hi Kamikaze,

Thank you very much for your suggestion. Coming from the Keil 51 arena I was hoping to be able to use the reentrant directive, I will dig a little deeper.

Best regards
Aaron
0 Likes
Not applicable
Keil supports the XMC 4500 and provides reentrant support: http://www.keil.com/dd/chips/infineon/arm.htm
0 Likes
Not applicable
Thanks Kamikaze.
0 Likes
Not applicable
Hi everyone,


Can anyone tell me if the DAVE 3 compiler creates reentrant functions by default or do I need to specify my functions as reentrant somehow ?


For example, if I want the following function to be called by Main() and an Interrupt at the same time how do I ensure it's local variables aren't corrupted ?


uint8_t Digital_Output(uint8_t OutputNumber, uint8_t NewState)
{
uint8_t OutputChanged = FALSE;


// Function code....................


return OutputChanged;
}


I come from a Keil C51 background which used the 'reentrant' directive at the function definition and I have also noticed the DAVE library functions such as 'ADC001_Init()' in ADC001.h use the 'Reentrant' directive.


Thank you very much
Best regards
Aaron
0 Likes