RE: DS80C400 reentrant multi tasking function calls with Keil compiler

"Bob Heise" <bheise-NP2g6PpLnQ18UrSeD/[email protected]>
Newsgroups gmane.comp.hardware.microcontrollers.tini
Message-ID <[email protected]>
Richard,

It's been several months since I worked on a DS80C400 project with the
reentrant keyword.  I don't remember the details but the conclusion I
reached at that time was to avoid "reentrant" altogether.  I examined the
assembly output from the compiler and I recall that it did not appear to be
reentrant at all!

My two work-arounds are:
1)  Sandwich non-blocking functions between calls to task_entercritsection()
and task_leavecritsection().  I created macros for this.
2)  Duplicate any routines that block and rename each one with a convention
of your choice.  I can see where this can get ugly, but it worked for me.

I used the previous version of the Keil tools, and thought they would have
fixed this by now.
Maybe someone else will have a better solution for you.

Hope this helps,
Bob





-----Original Message-----
From: tini-admin-6tN4nzCoH/[email protected] [mailto:[email protected]]On Behalf Of
DevUpdate
Sent: Thursday, February 26, 2004 8:21 AM
To: tini-6tN4nzCoH/[email protected]
Subject: [TINI]DS80C400 reentrant multi tasking function calls with Keil
compiler


Hi there,

I'm looking for some tips on how to correctly use C functions marked as
reentrant under a Keil development environment (C51 V7.08) on a Dallas
DS80C400.   I believe the startup400.a51 file is configured correctly
with USE_REENTRANT_STACK=1.  I have included example source at end of
the email.

Specifically I'm trying to call a reentrant function from multiple tasks
and an unable to do so without corrupting local function variables -
perhaps what I'm trying to do is inappropriate, but I'd like to know if
its possible and what I'm doing wrong.

I have successfully managed to demonstrate that recursive, reentrant
calls to an example reentrant function behave correctly, thus calls to
oozlum_bird() from a single task work as expected. ie output

-> oozlum_bird() PID:01 localfncvar: 0 anumber: 0
-> oozlum_bird() PID:01 localfncvar: 1 anumber: 1
-> oozlum_bird() PID:01 localfncvar: 2 anumber: 2
-> oozlum_bird() PID:01 localfncvar: 3 anumber: 3
<- oozlum_bird() PID:01 localfncvar: 3 anumber: 4
<- oozlum_bird() PID:01 localfncvar: 2 anumber: 3
<- oozlum_bird() PID:01 localfncvar: 1 anumber: 2
<- oozlum_bird() PID:01 localfncvar: 0 anumber: 1

This shows a local function variable being set  to anumber.   anumber is
incremented and passed as the input parameter to oozlum_bird().
oozlum_bird() returns after a number of recursive calls.  anumber is one
greater than it was initially as expected.

Calls to a non-reentrant version of the function give the expected
results of localfncvar being affected.

-> non_oozlum_bird() PID:01 localfncvar: 0 anumber: 0
-> non_oozlum_bird() PID:01 localfncvar: 1 anumber: 1
-> non_oozlum_bird() PID:01 localfncvar: 2 anumber: 2
-> non_oozlum_bird() PID:01 localfncvar: 3 anumber: 3
<- non_oozlum_bird() PID:01 localfncvar: 3 anumber: 4
<- non_oozlum_bird() PID:01 localfncvar: 3 anumber: 4
<- non_oozlum_bird() PID:01 localfncvar: 3 anumber: 4
<- non_oozlum_bird() PID:01 localfncvar: 3 anumber: 4

However, when I create two tasks to call the same function,  localfncvar
is affected between tasks as can be seen by the following output fragment:

-> oozlum_bird() PID:29 localfncvar: 1 anumber: 1
-> oozlum_bird() PID:53 localfncvar: 2 anumber: 2
-> oozlum_bird() PID:29 localfncvar: 3 anumber: 3
-> oozlum_bird() PID:53 localfncvar: 4 anumber: 4
<- oozlum_bird() PID:29 localfncvar: 4 anumber: 5
<- oozlum_bird() PID:53 localfncvar: 2 anumber: 3
<- oozlum_bird() PID:29 localfncvar: 1 anumber: 2
<- oozlum_bird() PID:53 localfncvar: 0 anumber: 1
<- oozlum_bird() PID:53 localfncvar: 0 anumber: 0


Any pointers to where I'm going wrong would be greatly appreciated.

Richard

Example code follows.


#include <stdio.h>             #include <string.h>            #include
"rom400_init.h"
#include "rom400_task.h"

//
// Some defines for the program run.
//
#define RAM_START             0x14000
#define RAM_END               0x6F000



void oozlum_bird(int anumber) reentrant;

#define CALL_DEPTH_LIMIT 4



/*
* This function should preserve automatic variables as it burrows down
into itself
*/
void oozlum_bird(int anumber) reentrant
{
 // I want this var to be unaffected by calls to function for different
tasks
 volatile unsigned localfncvar = 0;

 task_wait(0, 0, 2000);

 task_entercritsection();
   localfncvar = anumber;
   printf("-> oozlum_bird() PID:%b02x localfncvar: %d anumber: %d \r\n",
task_getcurrent(), localfncvar, anumber++);

 task_leavecritsection();

 // recursively call oozlum_bird() upto a call depth limit
 if (CALL_DEPTH_LIMIT > anumber)
 {
   oozlum_bird(anumber);
 }

 task_wait(0, 0, 2000);

 task_entercritsection();
   printf("<- oozlum_bird() PID:%b02x localfncvar: %d anumber: %d \r\n",
task_getcurrent(), localfncvar, anumber);
 task_leavecritsection();
}

/*
* Non reentrant version of oozlum_bird()
*/
void non_oozlum_bird(int anumber)
{

 volatile unsigned localfncvar = 0;

 task_wait(0, 0, 2000);

 task_entercritsection();
   localfncvar = anumber;
   printf("-> non_oozlum_bird() PID:%b02x localfncvar: %d anumber: %d
\r\n", task_getcurrent(), localfncvar, anumber++);

 task_leavecritsection();

 // recursively call oozlum_bird() upto a call depth limit
 if (CALL_DEPTH_LIMIT > anumber)
 {
   non_oozlum_bird(anumber);
 }

 task_wait(0, 0, 2000);

 task_entercritsection();
   printf("<- non_oozlum_bird() PID:%b02x localfncvar: %d anumber: %d
\r\n", task_getcurrent(), localfncvar, anumber);
 task_leavecritsection();
}


/*
* Spawn of process that repeatedly calls oozlum_bird()
*/
void spawn_test() reentrant
{
   unsigned int result;


   task_entercritsection();   // make sure we don't task swap before we
can get the result out
   result = task_fork(NORM_PRIORITY, ROM_SAVESIZE);

   if (result==0xFFFF)
   {
       task_leavecritsection();
       printf("Attempt to fork failed\r\n");
       return;
   }
   //else result is 0 for the child process, else it is the child PID

   if (result==0)
   {
       // This is the stuff that happens in the task just generated by
the fork call

     while(1)
     {
         oozlum_bird(0);
         task_wait(0, 0, 2000);
     }
   }
   else
   {
     // This is the parent task
     task_leavecritsection();

   }
}



void main(void)
{
   unsigned char ch;

   printf("\r\n Reentrant call investigation\r\n\r\n");

   printf("DS80C400 Initialization Library Version %d\r\n",
init_version());
   printf("DS80C400 Scheduler Library Version      %d\r\n",
task_version());

   printf("About to perform an init of the rom...\r\n\r\n");
   init_rom(RAM_START, RAM_END);

   task_settickreload(RELOAD_14_746);



   while (1)
   {
       //let's implement a menu system for this thing...
       printf("\r\n*********************************************\r\n");
       printf("       Reentrant call investigation             *\r\n");
       printf("                                                *\r\n");
       printf(" s - SPAWN an oozlum_bird process               *\r\n");
       printf(" o - Make call to oozlum_bird (recursive)       *\r\n");
       printf(" n - Make call to non_oozlum_bird               *\r\n");

       printf("Enter your choice: ");
       ch = getchar();
       printf("\r\n");
                     switch(ch)
       {


           case 's' : spawn_test();
                      break;

           case 'o' : oozlum_bird(0);
                       break;
           case 'n' : non_oozlum_bird(0);
                       break;
           default  : printf("Huh???\r\n");
       }
   }

   printf("\r\nThe program will now freeze.");

   while(1)
   {
   };
}








_______________________________________________
TINI mailing list
TINI-6tN4nzCoH/[email protected]
To UNSUBSCRIBE, edit your profile, or see list archives:
http://lists.dalsemi.com/mailman/listinfo/tini

_______________________________________________
TINI mailing list
TINI-6tN4nzCoH/[email protected]
To UNSUBSCRIBE, edit your profile, or see list archives:
http://lists.dalsemi.com/mailman/listinfo/tini
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.