Embedded Systems Practices
Embedded Systems Practices
The image presents common practices in real-time embedded systems, including modular
programming, state machines, polling vs. interrupt-driven approaches, timing algorithms,
memory management, function callbacks, resource access control, and circular buffers. Below is
an explanation of each topic along with corresponding C++ code examples.
1. Modular Programming
Explanation:
Code is structured into independent modules for better reusability, manageability, and testability.
This is achieved using separate files and header files in C++.
cpp
class Motor {
public:
void start();
void stop();
};
#endif
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 1/16
cpp
void Motor::start() {
std::cout << "Motor started" << std::endl;
}
void Motor::stop() {
std::cout << "Motor stopped" << std::endl;
}
cpp
int main() {
Motor motor;
motor.start();
motor.stop();
return 0;
}
2. State Machine
Explanation:
cpp
#include <iostream>
int main() {
State currentState = OFF;
std::cout << "Initial State: OFF" << std::endl;
currentState = buttonPressed(currentState);
std::cout << "New State: " << (currentState == ON ? "ON" : "OFF") << std::endl;
return 0;
}
#include <iostream>
#include <thread>
#include <chrono>
void interruptHandler() {
std::cout << "Key pressed! Handling interrupt..." << std::endl;
keyPressed = false; // Reset key state
}
void pollingMethod() {
while (true) {
if (keyPressed) {
interruptHandler();
}
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Simulate delay
}
}
int main() {
std::thread pollingThread(pollingMethod);
std::this_thread::sleep_for(std::chrono::seconds(2));
keyPressed = true; // Simulate key press
pollingThread.join();
return 0;
}
Explanation:
cpp
#include <iostream>
#include <chrono>
#include <thread>
void task() {
std::cout << "Executing scheduled task..." << std::endl;
}
int main() {
std::cout << "Task scheduled to run in 3 seconds..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(3));
task();
return 0;
}
Explanation:
Different memory allocation strategies such as stack, heap, and pool allocation.
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 3/16
C++ Code Example (Heap Allocation)
cpp
#include <iostream>
int main() {
int* ptr = new int(10); // Heap allocation
std::cout << "Heap allocated value: " << *ptr << std::endl;
delete ptr; // Free memory
return 0;
}
6. Function Callbacks
Explanation:
cpp
#include <iostream>
void callbackFunction() {
std::cout << "Callback function executed!" << std::endl;
}
int main() {
registerCallback(callbackFunction);
return 0;
}
Explanation:
cpp
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
int main() {
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 4/16
std::thread t1(accessResource, 1);
std::thread t2(accessResource, 2);
t1.join();
t2.join();
return 0;
}
8. Circular Buffers
Explanation:
Uses a fixed-size buffer with wrap-around indexing for efficient data storage.
cpp
#include <iostream>
#define SIZE 5
class CircularBuffer {
int buffer[SIZE];
int head = 0, tail = 0;
int count = 0;
public:
void enqueue(int value) {
if (count == SIZE) {
std::cout << "Buffer full!" << std::endl;
return;
}
buffer[tail] = value;
tail = (tail + 1) % SIZE;
count++;
}
int dequeue() {
if (count == 0) {
std::cout << "Buffer empty!" << std::endl;
return -1;
}
int value = buffer[head];
head = (head + 1) % SIZE;
count--;
return value;
}
};
int main() {
CircularBuffer cb;
cb.enqueue(1);
cb.enqueue(2);
cb.enqueue(3);
std::cout << "Dequeued: " << cb.dequeue() << std::endl;
cb.enqueue(4);
return 0;
}
Conclusion
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 5/16
Polling vs. Interrupts, Callbacks, and Resource Access Control are particularly important for
efficient system design.
Let me know if you need further details or enhancements in any specific area! 🚀
what else?
Apart from the common practices mentioned in the image, real-time embedded systems involve
several advanced techniques and optimizations that improve efficiency, responsiveness, and power
management. Below are additional crucial topics along with their C++ implementations.
Embedded systems often operate on battery power, requiring low-power modes like sleep, deep
sleep, and dynamic frequency scaling.
Techniques like clock gating, interrupt-based wake-up, and power-aware scheduling help
optimize energy consumption.
cpp
#include <iostream>
#include <thread>
#include <chrono>
void enterLowPowerMode() {
std::cout << "Entering low power mode..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5)); // Simulating deep sleep
std::cout << "Waking up from low power mode!" << std::endl;
}
int main() {
std::cout << "System running..." << std::endl;
enterLowPowerMode();
std::cout << "Resuming normal operation." << std::endl;
return 0;
}
🔹 In real hardware, you would use MCU sleep modes instead of `sleep_for`.
Real-Time Operating Systems (RTOS) use priority scheduling to determine which task should
execute.
Preemptive scheduling ensures that higher-priority tasks execute first.
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 6/16
C++ Code Example (Priority-based Scheduling)
cpp
#include <iostream>
#include <queue>
#include <functional>
struct Task {
int priority;
std::string name;
int main() {
std::priority_queue<Task> taskQueue;
while (!taskQueue.empty()) {
std::cout << "Executing: " << taskQueue.top().name << std::endl;
taskQueue.pop();
}
return 0;
}
Switches & buttons often generate multiple signals due to mechanical bounce.
A debounce algorithm filters out rapid unintended state changes.
cpp
#include <iostream>
#include <chrono>
#include <thread>
bool isButtonPressed() {
// Simulate button press with bouncing
static int count = 0;
count++;
return (count % 3 == 0); // Every 3rd read is an actual press
}
void debounceButton() {
bool lastState = false;
while (true) {
bool currentState = isButtonPressed();
if (currentState && !lastState) {
std::cout << "Button Pressed!" << std::endl;
}
lastState = currentState;
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Debounce delay
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 7/16
}
}
int main() {
debounceButton();
return 0;
}
cpp
#include <iostream>
int main() {
State currentState = RED;
for (int i = 0; i < 5; i++) {
nextState(currentState);
}
return 0;
}
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 8/16
C++ Code Example (Simple XOR Encryption)
cpp
#include <iostream>
#include <string>
int main() {
std::string msg = "HelloWorld";
char key = 'X';
return 0;
}
Embedded systems need real-time data logging to monitor sensor data, logs, and debugging
info.
cpp
#include <iostream>
#include <fstream>
#include <ctime>
int main() {
logData("System Started");
logData("Sensor value: 42");
logData("System Shutting Down");
return 0;
}
Embedded systems communicate via protocols like MQTT (IoT), CAN Bus (automotive), SPI, I2C.
Message Queuing Telemetry Transport (MQTT) is commonly used for IoT devices.
cpp
#include <iostream>
#include <queue>
std::queue<std::string> messageQueue;
void receiveMessage() {
if (!messageQueue.empty()) {
std::cout << "Received: " << messageQueue.front() << std::endl;
messageQueue.pop();
}
}
int main() {
sendMessage("Hello from Sensor 1");
sendMessage("Temperature: 23°C");
receiveMessage();
receiveMessage();
return 0;
}
Final Thoughts
Beyond the common practices in embedded systems, these advanced techniques help design
scalable, efficient, and secure real-time applications.
✅ Next Steps:
Implement RTOS-based scheduling (FreeRTOS)
Add interrupt-driven GPIO handling
Use hardware timers for precision timing
Implement real-time CAN Bus protocol
All
Got it! I'll provide detailed explanations and C++ implementations for the following real-time
embedded system topics:
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 10/16
🚀 Topics Covered:
1. RTOS-based scheduling (FreeRTOS)
2. Interrupt-driven GPIO handling
3. Hardware timers for precision timing
4. Real-time CAN Bus protocol
cpp
#include "FreeRTOS.h"
#include "task.h"
#include <Arduino.h> // Required for ESP32 or STM32 boards
void setup() {
Serial.begin(115200);
xTaskCreate(Task1, "Task 1", 1000, NULL, 1, NULL);
xTaskCreate(Task2, "Task 2", 1000, NULL, 2, NULL);
}
void loop() {
// Empty, since RTOS handles scheduling
}
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 11/16
cpp
#include <Arduino.h>
#define BUTTON_PIN 2
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), handleInterrupt, FALLING);
}
void loop() {
if (buttonPressed) {
Serial.println("Button Pressed!");
buttonPressed = false; // Reset flag
}
}
cpp
#include <Arduino.h>
void setup() {
Serial.begin(115200);
timer = timerBegin(0, 80, true); // Timer 0, prescaler 80 (1us resolution)
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true); // 1 second period
timerAlarmEnable(timer);
}
void loop() {
if (timerFlag) {
Serial.println("Timer Triggered!");
timerFlag = false;
}
}
🔹 ESP32 and STM32 use dedicated hardware timers for high precision.
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 12/16
4. Real-time CAN Bus Communication
Explanation:
Controller Area Network (CAN Bus) is used in automotive, industrial, and robotics
applications.
Uses message-based communication between multiple devices.
cpp
#include <ESP32CAN.h>
#include <CAN_config.h>
CAN_device_t CAN_cfg;
void setup() {
Serial.begin(115200);
CAN_cfg.speed = CAN_SPEED_500KBPS;
CAN_cfg.tx_pin_id = GPIO_NUM_5;
CAN_cfg.rx_pin_id = GPIO_NUM_4;
CAN_init();
}
void loop() {
CAN_frame_t frame;
frame.MsgID = 0x100;
frame.FIR.B.DLC = 8;
for (int i = 0; i < 8; i++) {
frame.data.u8[i] = i;
}
ESP32Can.CANWriteFrame(&frame);
delay(1000);
}
🔹 CAN Bus is essential for vehicle electronics, industrial automation, and robotic systems.
Final Thoughts
✅ We covered advanced real-time embedded system topics:
RTOS-based multitasking (FreeRTOS)
Interrupt-driven GPIO handling
High-precision hardware timers
Real-time CAN Bus communication
💡 Next Steps:
Implement SPI/I2C communication
Integrate real-time data logging
Optimize power consumption using deep sleep modes
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 13/16
Implement SPI/I2C communication
✅ Explanation
SPI (Serial Peripheral Interface) and I2C (Inter-Integrated Circuit) are common serial
communication protocols in embedded systems.
SPI is faster but requires more wires, while I2C supports multiple devices with just two wires.
1. SPI Communication
✅ How SPI Works
Full-duplex communication using four lines:
MOSI (Master Out, Slave In)
MISO (Master In, Slave Out)
SCK (Clock)
CS/SS (Chip Select)
Master controls the communication, and slaves respond.
cpp
#include <SPI.h>
#define SS_PIN 10
void setup() {
Serial.begin(115200);
SPI.begin();
pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN, HIGH);
}
void loop() {
digitalWrite(SS_PIN, LOW);
byte response = SPI.transfer(0x42); // Send data to slave
digitalWrite(SS_PIN, HIGH);
Slave Device
cpp
#include <SPI.h>
void setup() {
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 14/16
Serial.begin(115200);
SPI.begin();
pinMode(MISO, OUTPUT);
SPCR |= _BV(SPE); // Enable SPI in slave mode
SPI.attachInterrupt();
}
ISR(SPI_STC_vect) {
receivedData = SPDR; // Read received data
SPDR = receivedData + 1; // Send modified data back
}
void loop() {
Serial.print("Received: ");
Serial.println(receivedData, HEX);
delay(1000);
}
2. I2C Communication
✅ How I2C Works
Two-wire communication (SDA, SCL)
Supports multiple masters/slaves using device addresses.
Master initiates communication, and slave responds.
cpp
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(115200);
}
void loop() {
Wire.beginTransmission(SLAVE_ADDRESS);
Wire.write("Hello from Master");
Wire.endTransmission();
delay(500);
}
Slave Device
cpp
#include <Wire.h>
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 15/16
}
Serial.println();
}
void setup() {
Wire.begin(SLAVE_ADDRESS);
Wire.onReceive(receiveData);
Serial.begin(115200);
}
void loop() {
delay(1000);
}
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 16/16