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