Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.


State machines and pointer of functions DS80C

  • Mike

    I've tried this and would be grateful for any pointers (excuse pun) where I'm going wrong.  This is what I've tried but doesn't work.  FYI this is for
    the DS80C400.

    It works fine using DevC++ with the desired result.

    Thanks in advance.

    #include <stdio.h>
    #include "reg400.h"

    typedef enum {FUN1, FUN2, FUN3} state_type;

    state_type fun1(void)
    {   printf("\nFun1");   return FUN2; }

    state_type fun2(void)
    {   printf("\nFun2");   return FUN3; }

    state_type fun3(void)
    {   printf("\nFun3");   return FUN1; }

    state_type (*state_table [] ) () = {fun1, fun2, fun3};

    int main(void)
       int        i;
       state_type current_state;

       current_state = FUN1;
       for (i = 0; i < 10; i++) {
          current_state = state_table[current_state]();
       return 0;

    The batch program to compile and link:

    asx8051 -losffgp startup400.a51

    sdcc -c -v -mds400 --model-flat24 --stack-10bit --no-xinit-opt -I/usr/local/share/sdcc/include main.c

    sdcc --verbose --dumpall -mds400 --model-flat24 --stack-10bit -Wl-r --xram-loc 0x10000 --code-loc 0x400000 main.rel startup400.rel -l rominit.lib

    packihx main.ihx>main.hex

    • Maarten Brock
      Maarten Brock

      "Doesn't work"... Does that mean you get an error message?

      But in general, if you want to use function pointers, I recommend to use a typedef. Something like:

      typedef state_type (*pfnState)(void);
      pfnState state_table[] = {fun1, fun2, fun3};

      Hope this helps,

      • Mike

        Many thanks for your input.

        The problem is I don't get any compiler warnings or messages.  The program just hangs as soon as I impliment the pointer.

        I tried your suggestion but I get the same result.  I've resorted to using switch but this method is more ornate.

        The code is a bit difficult to follow.  The table is in xdata and the code seems to load in the table of 24 bit addresses.  At first sight it looks as it should work but havn't been able to follow the code completely.  Also can't then easily see what happens after linking!

    • Maarten Brock
      Maarten Brock

      After linking have a look at the *.rst files. They contain address info.

    • Tim Michals
      Tim Michals

      The problem is that functions in Keil require special care if you want to call them from multiple processes at the same time (I am trying to avoid the word reentrant because Keil has a 'reentrant' keyword that does not quite do the trick). Keil uses XDATA locations for variables and some function arguments, depending on the function signature (see chapter 6 of tthe Cx51 Compiler Guide for more on this). The problem is that these are not implemented on a software stack, but are static addresses, so when another process calls the same function, the two processes step on each others variables. In the case of the original poster's code, the first child process had not started running by the time the parent called the 'SpawnTask' function again, so the 'task' argument got overridden, and both child processes ended up using this overridden 'task' argument. One solution is to store the 'task' argument in a variable declared as DATA, because those variables are swapped on process swaps.