2013-04-23 3 views
0

В настоящее время я программирования ПИК в C с MPLAB X (+ компилятор XC8)Как реализовать стек, содержащий вызов функции для ПОС в C

В моем коде, у меня есть некоторые перерывы (inter1, inter2, ..), каждый из которых состоит из срочных и несрочных операций (срочные, срочные, .., n_urg1, n_urg2, ..).

Так что я хотел бы код со следующей структурой:

stack s; // FIFO or other 
main() { 
    while (true) { 
     if (!isEmpty(s)) { 
     doNextFunction(s); 
     } 
    } 
} 

void interrupt inter1() { 
    urg1(); // urgent code 
    addStack(n_urg1); 
} 

void n_urg1() { 
    // non-urgent code 
} 

Как я могу реализовать такой стек? Есть ли что-то в стандартной библиотеке?

ответ

1

Если я правильно помню, то этот компилятор довольно примитивен, я не думаю, что вы можете использовать библиотеку std.

Если вам нужно выполнить все это самостоятельно, вы можете использовать массив указателей на функции:

#include <string.h> // for memmove() 

#define STACK_MAX 10 

typedef enum 
{ 
    Int, 
    Boolean 
} VariantType; 

typedef struct 
{ 
    VariantType type; 
    union { 
     int intValue; 
     bool booleanValue; 
    } value; 
} Variant; 

typedef bool (*FunctionPtr)(Variant data); 

typedef struct 
{ 
    FunctionPtr ptr; 
    Variant var; 
} FunctionCall; 

FunctionCall functionStack[STACK_MAX]; 
int functionStackUse = 0; 

bool addStack(FunctionPtr ptr, Variant var) 
{ 
    if (functionStackUse >= STACK_MAX) 
     return false; // stack full 
    functionStack[functionStackUse].ptr = ptr; 
    functionStack[functionStackUse].var = var; 
    functionStackUse++; 
    return true; 
} 

bool callNextFunction(void) 
{ 
    // TODO: disable inter1 
    if (functionStackUse > 0) 
    { 
     // get first function on stack 
     FunctionCall functionCall = functionStack[0]; 
     functionStackUse--; 
     // remove first function from stack 
     memmove((void*)functionStack, (void*)(functionStack + 1), functionStackUse * sizeof(functionStack[0])); 
     // TODO: re-enable inter1 
     // call function with arguments 
     return (*functionCall.ptr)(functionCall.var); 
    } 
    else 
    { 
     // TODO: re-enable inter1 
     return false; // no more functions 
    } 
} 

void main() 
{ 
    while (1) 
    { 
     callNextFunction(); 
     // TODO add some delay otherwise you're constantly disabling inter1 (in doNextFunction) 
    } 
} 


bool n_urg1(Variant var) 
{ 
    if (var.type == Int) 
    { 
     int i = var.value.intValue; 
     // do something 
     return true; 
    } 
    return false; 
} 

void inter1(void) 
{ 
    Variant var; 
    var.type = Int; 
    var.value.intValue = 45; 
    addStack(n_urg1, var); 
} 
+0

Спасибо большое! Но почему я должен отключать прерывания при вызове doNextFunction? В моем реальном коде у меня много функций «inter» и «n_urg». И цель состоит в том, что функции «n_urg» могут прерываться всеми функциями «inter». Я думаю, что мьютекс (как и ответ ниже) может исправить доступ к проблеме стека, не так ли? – DouglasAdams

+0

А что, если некоторым функциям «n_urg» нужны аргументы? – DouglasAdams

+0

Сначала вы берете указатель на функцию из стека и вызываете n_urg после повторного включения прерываний, я обновляю свой ответ. Весь ваш метод должен получить тот же аргумент (ы), иначе вы не сможете создать массив. –