Interação por Mensagens em Arquitetura de Software Embarcado

Em sistemas embarcados, a comunicação direta entre módulos de aplicação pode gerar acoplamento indesejado. Considere um dispositivo com módulos de interface homem-máquina (HMI) e comnuicação, onde a troca de dados através de chamadas diretas ou variáveis globais compromete a manutenibilidade.

Uma solução eficaz é empregar uma camada comum para implementar o padrão Observer, permitindo desacoplamento. Este padrão utiliza callbacks para notificações, onde um módulo publica eventos e outros se inscrevem para atualizações.

As vantagens incluem desacoplamento entre módulos, facilidade para adicionar ou remover observadores sem alterar o código do sujeito, e maior estabilidade do sistema. No entanto, desvantagens podem surgir, como atrasos nas notificações se callbacks forem numerosos ou lentos, além do risco de dependências circulares que levam a travamentos.

Para mitigar problemas, callbacks devem ser concisos e evitar chamadas recursivas entre observadores.

A seguir, um exemplo de implementação em C com nomes de variáveis e estruturas modificados.

Definições do Sistema de Eventos

#ifndef EVENT_DISPATCHER_H
#define EVENT_DISPATCHER_H

#include <stdint.h>

typedef enum {
    MOD_INTERFACE = 0,
    MOD_CONFIG,
    MOD_TOTAL
} ModuleTag;

typedef enum {
    EVT_CONFIG_REFRESH,
    EVT_NUM
} EventTag;

typedef struct {
    uint16_t reg_id;
    uint32_t value;
} ConfigUpdatePayload;

typedef int (*EventHandler)(ModuleTag source, EventTag event, const void *payload, uint32_t size);

extern void InitEventDispatcher(void);
extern int RegisterHandler(ModuleTag listener, EventTag event, EventHandler handler);
extern int UnregisterHandler(ModuleTag listener, EventTag event);
extern int DispatchEvent(ModuleTag source, EventTag event, const void *payload, uint32_t size);

#endif
</stdint.h>

Implementação do Sistema de Eventos

#include "event_dispatcher.h"
#include <string.h>

static EventHandler handler_table[MOD_TOTAL][EVT_NUM];

void InitEventDispatcher(void) {
    memset(handler_table, 0, sizeof(handler_table));
}

int RegisterHandler(ModuleTag listener, EventTag event, EventHandler handler) {
    if (listener >= 0 && listener < MOD_TOTAL && event < EVT_NUM) {
        handler_table[listener][event] = handler;
        return 0;
    }
    return -1;
}

int UnregisterHandler(ModuleTag listener, EventTag event) {
    if (listener >= 0 && listener < MOD_TOTAL && event < EVT_NUM) {
        handler_table[listener][event] = NULL;
        return 0;
    }
    return -1;
}

int DispatchEvent(ModuleTag source, EventTag event, const void *payload, uint32_t size) {
    if (event < EVT_NUM) {
        for (int idx = 0; idx < MOD_TOTAL; idx++) {
            if (handler_table[idx][event] != NULL) {
                handler_table[idx][event](source, event, payload, size);
            }
        }
        return 0;
    }
    return -1;
}
</string.h>

Módulo de Gerenciamento de Configuração

#include "event_dispatcher.h"

static int ConfigEventHandler(ModuleTag source, EventTag event, const void *payload, uint32_t size);

void ConfigModuleInit(void) {
    RegisterHandler(MOD_CONFIG, EVT_CONFIG_REFRESH, ConfigEventHandler);
}

int ConfigEventHandler(ModuleTag source, EventTag event, const void *payload, uint32_t size) {
    if (event == EVT_CONFIG_REFRESH) {
        ConfigUpdatePayload *info = (ConfigUpdatePayload *)payload;
        PersistConfiguration(info->reg_id, info->value);
    }
    return 0;
}

Módulo de Interface

#include "event_dispatcher.h"

void InterfaceModuleInit(void) {
    // Configuração inicial
}

int TriggerConfigUpdate(void) {
    ConfigUpdatePayload data;
    data.reg_id = 5;
    data.value = 20;
    return DispatchEvent(MOD_INTERFACE, EVT_CONFIG_REFRESH, &data, sizeof(ConfigUpdatePayload));
}

Tags: C embedded-systems observer-pattern event-driven modular-design

Publicado em 5-30 05:42 por Thomas