Claim Your Discount Today
Take your coding game to new heights with expert help at unbeatable prices. Got a tricky project or a tight deadline? We’ve got you covered! Use code PHHBF10 at checkout and save BIG. Don’t wait—this exclusive Black Friday deal won’t last long. Secure your academic success today!
We Accept
- Setting Up the Project
- Creating the Eclipse Project
- Setting Up the Simulation Server
- Implementing the Round-Robin Scheduler
- Defining Function Pointers and Linked List Structure
- Creating Task Prototypes
- Main Function
- Implementing System Tasks
- Task 1: Sensor / Temperature Data
- Task 2: Button Press Detection
- Task 3: Set Mode
- Filtering and Displaying Data
- Task 4: Filter Mode
- Task 5: Display Update
- Task 6: Check Exit Condition
- Testing and Debugging
- Testing Individual Tasks
- Integrating and Testing All Tasks
- Debugging Common Issues
- 1. Socket Connection Issues:
- 2. Task Synchronization Problems:
- 3. Unexpected Task Behavior:
- Conclusion
In this blog post, we will walk through the implementation of a circular linked list in C, which holds function pointers to manage tasks for a body thermometer system. This project is divided into two main activities: creating the program shell and implementing the full system functionality. If you're seeking help with C Assignment, this guide will be particularly beneficial. We'll cover the setup, coding, and testing processes necessary to complete these activities.
Setting Up the Project
Before diving into the code, it's essential to set up the project environment correctly. This section covers the initial setup steps, creating the project in Eclipse, and preparing the simulation server.
Creating the Eclipse Project
To begin, you need to create a new project in Eclipse.
1. Starting a New Project:
- Open Eclipse.
- Navigate to File -> New -> C/C++ Project.
- Select C Managed Build and name the project M6Lab.
- Choose Hello World ANSI C Project and Cross GCC.
2. Project Configuration:
- Once the project is created, replace the default main.c file with our starter code.
- Add the necessary header files for socket communication:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
Setting Up the Simulation Server
The simulation server runs on your host platform and provides simulated register and temperature values.
1. Creating the Simulation Server Project:
- Start a new project in Eclipse: File -> New -> C/C++ Project.
- Select C Managed Build and name the project SimulationServer.
- Choose Hello World ANSI C Project and Linux GCC.
2. Configuring the Simulation Server:
- Replace the default source file with SimulationServer.c.
- Modify the IP addresses in the TempServer and RegTemp functions to match your server's IP.
- Change the build configuration to Release.
- Add -pthread to the linker options under project properties.
Implementing the Round-Robin Scheduler
With the project setup complete, we move on to implementing the round-robin scheduler using a circular linked list. This section includes the definition of function pointers, the structure of the linked list, and the main loop.
Defining Function Pointers and Linked List Structure
First, we define a generic function pointer and the structure for our linked list nodes.
typedef void* (*FunctionPointer)(double *, int *, char *, char *);
typedef void* (*FunctionPointer)(double *, int *, char *, char *);
typedef struct fcnNode {
FunctionPointer fcnPtr;
struct fcnNode *nextNode;
} fcnNode;
Creating Task Prototypes
Next, we declare prototypes for each of our six system tasks.
void * T1(double *, int *, char *, char *);
void * T2(double *, int *, char *, char *);
void * T3(double *, int *, char *, char *);
void * T4(double *, int *, char *, char *);
void * T5(double *, int *, char *, char *);
void * T6(double *, int *, char *, char *);
Main Function
The main function initializes shared resources, creates the circular linked list, and starts the round-robin loop.
int main() {
double currentTemp = 0;
int exitLoop = 0;
char tempVal = (char)0x00;
char regVal = (char)0x00;
fcnNode *headerNode = malloc(sizeof(fcnNode));
fcnNode *currentNode = headerNode;
currentNode->fcnPtr = &T1;
currentNode->nextNode = malloc(sizeof(fcnNode));
currentNode = currentNode->nextNode;
currentNode->fcnPtr = &T2;
currentNode->nextNode = malloc(sizeof(fcnNode));
currentNode = currentNode->nextNode;
currentNode->fcnPtr = &T3;
currentNode->nextNode = malloc(sizeof(fcnNode));
currentNode = currentNode->nextNode;
currentNode->fcnPtr = &T4;
currentNode->nextNode = malloc(sizeof(fcnNode));
currentNode = currentNode->nextNode;
currentNode->fcnPtr = &T5;
currentNode->nextNode = malloc(sizeof(fcnNode));
currentNode = currentNode->nextNode;
currentNode->fcnPtr = &T6;
currentNode->nextNode = headerNode;
currentNode = headerNode;
while (!exitLoop) {
FunctionPointer fun = currentNode->fcnPtr;
fun(¤tTemp, &exitLoop, &tempVal, ®Val);
currentNode = currentNode->nextNode;
}
printf("Goodbye!\n");
return 0;
}
Implementing System Tasks
This section details the implementation of each system task, including sensor data handling, button presses, mode filtering, and LCD updates.
Task 1: Sensor / Temperature Data
Task 1 reads the SSR and SDR registers from the simulation server.
void * T1(double *currentTemp, int *exitLoop, char *tempVal, char *regVal) {
int socketfd, len, result, BUF_SIZE = 1;
struct sockaddr_in address;
char buffer;
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1"); // Update with actual server IP
address.sin_port = htons(5000);
result = connect(socketfd, (struct sockaddr *)&address, sizeof(address));
if (result == -1) {
printf("connection to server failed...\n");
close(socketfd);
return NULL;
}
// Read SSR
len = write(socketfd, "READSSR", BUF_SIZE);
len = read(socketfd, &buffer, BUF_SIZE);
*regVal = buffer;
// Read SDR
len = write(socketfd, "READSDR", BUF_SIZE);
len = read(socketfd, &buffer, BUF_SIZE);
*tempVal = buffer;
close(socketfd);
return NULL;
}
Task 2: Button Press Detection
Task 2 detects button presses by checking the register values read by Task 1.
Task 2 detects button presses by checking the register values read by Task 1.
void * T2(double *currentTemp, int *exitLoop, char *tempVal, char *regVal) {
if (*regVal & 0x01) {
printf("Button Press Detected!\n");
}
return NULL;
}
Task 3: Set Mode
Task 3 sets the mode based on the button press detected by Task 2.
void * T3(double *currentTemp, int *exitLoop, char *tempVal, char *regVal) {
static int mode = 0;
if (*regVal & 0x01) {
mode = (mode + 1) % 3; // Cycle through modes 0, 1, 2
printf("Mode changed to %d\n", mode);
}
return NULL;
}
Filtering and Displaying Data
This section discusses filtering temperature data and updating the LCD display.
Task 4: Filter Mode
Task 4 applies a filter based on the current mode to the temperature value read by Task 1.
void * T4(double *currentTemp, int *exitLoop, char *tempVal, char *regVal) {
static double lastTemp = 0;
static int mode = 0;
if (mode == 0) {
*currentTemp = *tempVal; // No filter
} else if (mode == 1) {
*currentTemp = (lastTemp + *tempVal) / 2; // Simple average
} else if (mode == 2) {
*currentTemp = 0.8 * lastTemp + 0.2 * *tempVal; // Exponential smoothing
}
lastTemp = *currentTemp;
printf("Filtered Temperature: %.2f\n", *currentTemp);
return NULL;
}
Task 5: Display Update
Task 5 updates the LCD display with the current temperature value.
void * T5(double *currentTemp, int *exitLoop, char *tempVal, char *regVal) {
printf("Updating Display: %.2f\n", *currentTemp);
// Code to update the LCD would go here
return NULL;
}
Task 6: Check Exit Condition
Task 6 checks if the exit condition is met, allowing the program to terminate gracefully.
void * T6(double *currentTemp, int *exitLoop, char *tempVal, char *regVal) {
static int counter = 0;
counter++;
if (counter >= 100) {
*exitLoop = 1;
}
return NULL;
}
Testing and Debugging
In this section, we cover the procedures for testing and debugging the system to ensure it functions correctly.
Testing Individual Tasks
Testing each task individually is crucial to verify its functionality.
Task 1: Sensor / Temperature Data
Test Task 1 by running the simulation server and checking if the program reads the SSR and SDR registers correctly.
int main() {
double currentTemp = 0;
int exitLoop = 0;
char tempVal = (char)0x00;
char regVal = (char)0x00;
T1(¤tTemp, &exitLoop, &tempVal, ®Val);
printf("Temperature Value: %d, Register Value: %d\n", tempVal, regVal);
return 0;
}
Task 2: Button Press Detection
Simulate button presses by setting the regVal manually and check if Task 2 detects them.
int main() {
double currentTemp = 0;
int exitLoop = 0;
char tempVal = (char)0x00;
char regVal = (char)0x01; // Simulate button press
T2(¤tTemp, &exitLoop, &tempVal, ®Val);
return 0;
}
Task 3: Set Mode
Check if Task 3 changes the mode correctly when a button press is detected.
int main() {
double currentTemp = 0;
int exitLoop = 0;
char tempVal = (char)0x00;
char regVal = (char)0x01; // Simulate button press
T3(¤tTemp, &exitLoop, &tempVal, ®Val);
return 0;
}
Integrating and Testing All Tasks
After testing individual tasks, integrate them into the main program and test the complete system.
int main() {
double currentTemp = 0;
int exitLoop = 0;
char tempVal = (char)0x00;
char regVal = (char)0x00;
fcnNode *headerNode = malloc(sizeof(fcnNode));
fcnNode *currentNode = headerNode;
currentNode->fcnPtr = &T1;
currentNode->nextNode = malloc(sizeof(fcnNode));
currentNode = currentNode->nextNode;
currentNode->fcnPtr = &T2;
currentNode->nextNode = malloc(sizeof(fcnNode));
currentNode = currentNode->nextNode;
currentNode->fcnPtr = &T3;
currentNode->nextNode = malloc(sizeof(fcnNode));
currentNode = currentNode->nextNode;
currentNode->fcnPtr = &T4;
currentNode->nextNode = malloc(sizeof(fcnNode));
currentNode = currentNode->nextNode;
currentNode->fcnPtr = &T5;
currentNode->nextNode = malloc(sizeof(fcnNode));
currentNode = currentNode->nextNode;
currentNode->fcnPtr = &T6;
currentNode->nextNode = headerNode;
currentNode = headerNode;
while (!exitLoop) {
FunctionPointer fun = currentNode->fcnPtr;
fun(¤tTemp, &exitLoop, &tempVal, ®Val);
currentNode = currentNode->nextNode;
}
printf("Goodbye!\n");
return 0;
}
Debugging Common Issues
When integrating and testing the system, you may encounter common issues such as incorrect socket connections, task synchronization problems, or unexpected task behavior.
1. Socket Connection Issues:
- Ensure the simulation server is running and listening on the correct IP and port.
- Check firewall settings that may block socket connections.
2. Task Synchronization Problems:
- Use printf statements to trace task execution order and timing.
- Ensure shared variables are accessed correctly without race conditions.
3. Unexpected Task Behavior:
- Verify task logic and ensure they operate on correct data values.
- Test tasks with different input scenarios to cover edge cases.
Conclusion
Implementing a circular linked list with function pointers for a round-robin scheduler in C provides a robust framework for managing multiple tasks in a body thermometer system. By carefully setting up the project, defining the task functions, and testing each component, we can build a reliable and efficient scheduling system. This approach can be extended to other embedded systems and real-time applications, demonstrating the flexibility and power of function pointers and circular linked lists in programming assignment.