This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

how to call malloc() or free() in interrupt function

my problem is how to use malloc or free function in interrupt function,because the function like malloc() or free() is non_reentrant.But i have to do it in interrupt function to save memory. what shall i do? please help me!
i use timer0 to free the memory when memeory is no applied,but after three times,the timero is closed auto.
the warning is:
multi call to a segment free() or malloc();
i describe my algorithm as below:
1)i make the data to link list firstly;
2)in timer0, i will write the node of the link list to CAN bus buffer, after it ,i will free the node.but the timer0 just work 3 times,when it gets the fourth ,the timer0 is closed auto, what shall i do??
regards!!
thanks !!

  • I would strongly urge you not to use malloc() at all, and definitely not from an ISR. If you are absolutely determined to use malloc(), you should set a flag in your ISR and take whatever action is necessary in your main program loop.

    Stefan

  • "i have to do it in interrupt function to save memory"

    How does that "save" memory???

  • Malloc etc are C features extremely unsuited for the '51. 'Saving memory' is accomplished by local storage which the Keil compiler will overlay. That, of course, can not be done for an ISR. Since an interrupt can happen any time, including when main is using max memory, using malloc in an ISR will save absolutely nothing.

    Embedded '51 C is not just C it requires understanding of the processor and its (dis)advantages. Do not program the '51 by 'college C' it will not work.

    Erik

  • The memory pool accessed via malloc() is a shared resource, with shared internal data structures. Like any shared resource, if you are going to use it from two different contexts -- such as the main code and an ISR -- you're going to need to assure that only one context can have access to the critical section at a time. In short, all your accesses to malloc() will have to be wrapped in calls to disable the interrupt that also calls malloc(). (The other solutions to reentrancy -- writing two routines or declaring the routine reentrant -- do not apply in this case because it's not the code in the function that's the problem so much as the shared memory heap.)

    Malloc has a relatively long and variable execution time that may make it undesirable in your interrupt handler.

    Do you really need a linked list for your CAN data to be output, or will a ring buffer do? Unless you actually need the ability of the list to insert into the middle of existing data, the list management is likely to be overhead you don't need.

  • "Unless you actually need the ability of the list to insert into the middle of existing data"

    You don't even need malloc to do that!
    Just have a fixed-size pool of list entries, which are either "free" or "in-use"

    You can then easily take a "free" entry and "splice" it anywhere into your "in-use" list by simply adjusting the link pointers.

  • See the following pseudo codes...

    void *MyMalloc (size_t s)
    {
        void *p;
        DisableISR;
        p=malloc(s);
        EnableISR;
        retrun p;
    }
    
    void MyFree (void *p)
    {
        DisableISR;
        free(p);
        EnableISR;
    }
    
    int main (void)
    {
        p=MyMalloc(x);//malloc().
        ...
        MyFree(p);//free().
    }
    
    
    void ISRxx (void)
    {
        p=malloc(x);
        ...
        free(p);
    }
    
    

  • or look at the DISABLE pragma - see the Manual