The Singleton Pattern is a design pattern that ensures a single instance of a structure and provides a global point of access to that instance.
Implementing the Singleton Pattern in Embedded C: Ensuring Universal UART Configuration
Introduction
In embedded systems development, efficiency and resource management are critical. The Singleton Pattern is a design pattern that ensures a single instance of a structure and provides a global point of access to that instance. This pattern is particularly valuable in embedded C programming, where resource utilization and memory management are crucial. In this article, we'll explore how to implement the Singleton Pattern in embedded C to ensure a single instance and provide a real-time code example to demonstrate its practical application.
Understanding the Singleton Pattern
The Singleton Pattern guarantees that a structure has only one instance throughout the program's lifetime. It achieves this by controlling the access to the instance and ensuring that only one instance is created. Subsequent requests for the instance return the same object, preventing the creation of multiple instances and ensuring global access to it.
Example: Implementing Singleton Pattern for Serial Communication Manager
Let's consider an example of an embedded system that communicates with multiple external devices using UART (Universal Asynchronous Receiver/Transmitter). We need a Serial Communication Manager to handle communication with these devices efficiently. The Serial Communication Manager should be a Singleton to avoid multiple instances and ensure a single point of access.
#include <stdio.h>
#include <stdbool.h>
// UART Communication Configurations (example, replace with actual UART configuration)
typedef struct {
int baud_rate;
bool parity;
// Add other configurations...
} UartConfig;
// Singleton Serial Communication Manager Structure
typedef struct {
UartConfig uart_config;
// Add other members and methods as needed...
} SerialCommunicationManager;
// Global static instance of Serial Communication Manager
static SerialCommunicationManager communication_manager_instance = { { 9600, false } }; // Initialized to default values
// Singleton function to get the Serial Communication Manager instance
SerialCommunicationManager* getSerialCommunicationManagerInstance() {
// Perform initialization only once
if (communication_manager_instance.uart_config.baud_rate == 0) {
// Initialize UART configuration
communication_manager_instance.uart_config.baud_rate = 9600;
communication_manager_instance.uart_config.parity = false;
// Initialize other UART configurations...
// Additional initialization code can be placed here.
}
return &communication_manager_instance;
}
// Function to send data via UART
void sendDataViaUart(const char* data) {
// Get Serial Communication Manager instance
SerialCommunicationManager* communication_manager = getSerialCommunicationManagerInstance();
// UART send implementation using the configuration
printf("Sending data via UART: %s\n", data);
printf("UART Baud Rate: %d\n", communication_manager->uart_config.baud_rate);
printf("UART Parity: %s\n", communication_manager->uart_config.parity ? "Enabled" : "Disabled");
// UART implementation details...
// Additional UART send code...
}
int main() {
// Get the Serial Communication Manager instance
SerialCommunicationManager* comm_manager = getSerialCommunicationManagerInstance();
// Use the Serial Communication Manager to send data via UART
sendDataViaUart("Hello, world!");
// Change the Baud Rate universally
comm_manager->uart_config.baud_rate = 115200;
// Use the updated Serial Communication Manager to send data via UART
sendDataViaUart("Hello again!");
return 0;
}
Output
Sending data via UART: Hello, world!
UART Baud Rate: 9600
UART Parity: Disabled
Sending data via UART: Hello again!
UART Baud Rate: 115200
UART Parity: Disabled
Explanation
Don't Miss an Update!
Helping you navigate the Embedded Systems career with ease! Technical posts, newsletters, special offers, and more.