DS80C400 reentrant multi tasking function calls with Keil compiler

DevUpdate <[email protected]>
Newsgroups gmane.comp.hardware.microcontrollers.tini
Organization Cyanica
Message-ID <[email protected]>
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
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.