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