Печать
Родительская категория: Заметки
Категория: Программирование микроконтроллеров
Просмотров: 403
Звезда не активнаЗвезда не активнаЗвезда не активнаЗвезда не активнаЗвезда не активна
 

Understanding Function Queues in C

Function queues are a powerful programming construct, particularly useful in embedded systems and real-time applications. This article explains a set of macros implemented in C to handle various types of function queues, including standard queues, delayed queues, and parameterized queues.

1. Standard Function Queue

The fQ macro defines a basic circular queue to store and execute function pointers. It includes:

#define fQ(q, Q_SIZE)                            \
    volatile int q##_last = 0;                   \
    int q##_first = 0;                           \
    void (*q##_Queue[Q_SIZE])(void);             \
    int q##_Push(void (*pointerQ)(void)) {       \
        if ((q##_last + 1) % Q_SIZE == q##_first)\
            return 1; /* Queue is full */        \
        q##_Queue[q##_last++] = pointerQ;        \
        q##_last %= Q_SIZE;                      \
        return 0; /* Success */                  \
    }                                            \
    int (*q##_Pull(void))(void) {                \
        if (q##_last == q##_first)               \
            return 1; /* Queue is empty */       \
        q##_Queue[q##_first++]();                \
        q##_first %= Q_SIZE;                     \
        return 0;  /* Success */ 		 \
    }

2. Delayed Function Queue

The del_fQ macro extends the standard queue to support delayed execution:

#define del_fQ(q, Q_SIZE)                                           \
    int q##_time = 0;                                               \
    void (*q##_del_fQueue[Q_SIZE])(void);                           \
    int q##_execArr[Q_SIZE] = { 0 };   	                            \
    int q##_execTime[Q_SIZE];                                       \
    fQ(q, Q_SIZE)                                                   \
    int q##_Push_delayed(void (*pointerF)(void), int delayTime){    \
        int q##_fullQ = 1;                                          \
        for (int i = 0; i < Q_SIZE; i++) {                          \
            if (!q##_execArr[i]) {                                  \
                q##_del_fQueue[i] = pointerF;                       \
                q##_execArr[i] = 1;                                 \
                q##_execTime[i] = q##_time + delayTime;             \
                q##_fullQ = 0;                                      \
                break;                                              \
            }                                                       \
        }                                                           \
        return q##_fullQ;                                           \
    }                                                               \
    void q##_Tick(void){                                            \
        for (int i = 0; i < Q_SIZE; i++) {                          \
            if (q##_execTime[i] == q##_time) {                      \
                if (q##_execArr[i]) {                               \
                    q##_Push(q##_del_fQueue[i]);                    \
                    q##_execArr[i] = 0;                             \
                }                                                   \
            }                                                       \
        }                                                           \
        q##_time++; /* Increment time */                            \
    }                                                               \
    int q##_Revoke(void (*pointerF)(void)){                         \
        int result = 1;                                             \
        for (int i = 0; i < Q_SIZE; i++) {                          \
            if (q##_del_fQueue[i] == pointerF) {                    \
                q##_execArr[i] = 0;                                 \
                result = 0;                                         \
            }                                                       \
        }                                                           \
        return result;                                              \
    }

3. Parameterized Function Queue

The fQP macro allows parameterized function execution:

#define fQP(q, Q_SIZE, param_type)                                      	\
    void (*q##_funcs[Q_SIZE])(param_type);                                      \
    param_type q##_params[Q_SIZE];                                              \
    volatile int q##_last = 0;                                                  \
    int q##_first = 0;                                                          \
    int q##_Push(void (*func)(param_type), param_type params) {                 \
        if ((q##_last + 1) % Q_SIZE == q##_first)                               \
            return 1; /* Queue is full */                                       \
        q##_funcs[q##_last] = func;                                             \
        q##_params[q##_last++] = params;                                        \
        q##_last %= Q_SIZE;                                                     \
        return 0; /* Success */                                                 \
    }                                                                           \
    int q##_Pull(void) {                                                        \
        if (q##_last == q##_first)                                              \
            return 1; /* Queue is empty */                                      \
        q##_funcs[q##_first](q##_params[q##_first++]);                          \
        q##_first %= Q_SIZE;                                                    \
        return 0; /* Success */                                                 \
    }

Key Features

These macros provide:

Use Cases

Function queues are particularly useful in:

find more here: ANTIRTOS#C

Conclusion

The macros presented here demonstrate a flexible and efficient way to manage function queues in C. By integrating these techniques into your projects, you can streamline task scheduling, improve resource management, and enhance the overall functionality of your software.

 
www.38i.ru