1
0
mirror of https://github.com/thiagoralves/OpenPLC.git synced 2025-05-09 00:21:52 +08:00

Added persistent storage to the OpenPLC! :)

This commit is contained in:
thiagoralves 2016-03-09 20:49:29 -06:00
parent 5dbfec2d80
commit b67eea7c13
3 changed files with 133 additions and 3 deletions

View File

@ -56,10 +56,10 @@ extern pthread_mutex_t bufferLock;
//hardware_layer.cpp
void initializeHardware();
void sendOutput(unsigned char *sendBytes, unsigned char *recvBytes);
void updateBuffers();
//openplc.cpp
void sleep_thread(int milliseconds);
void *modbusThread();
void PlcCycle(void); //read inputs, process them according to the ladder software and set outputs
@ -71,6 +71,10 @@ void processMessage(unsigned char *buffer, int bufferSize);
void *handleConnections(void *arguments);
void startServer(int port);
//persistent_storage.cpp
void *persistentStorage(void *args);
int readPersistentStorage();
//modbus.cpp
//Declaration of the supported modbus functions and the respective function code
enum MB_FC

View File

@ -34,6 +34,18 @@ using namespace std;
pthread_mutex_t bufferLock; //mutex for the internal buffers
//-----------------------------------------------------------------------------
// Helper function - Makes the running thread sleep for the ammount of time
// in milliseconds
//-----------------------------------------------------------------------------
void sleep_thread(int milliseconds)
{
struct timespec ts;
ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = (milliseconds % 1000) * 1000000;
nanosleep(&ts, NULL);
}
void *modbusThread(void *arg)
{
startServer(502);
@ -70,14 +82,20 @@ int main(void)
//======================================================
initializeHardware();
updateBuffers();
struct timespec timer_start;
pthread_t thread;
pthread_create(&thread, NULL, modbusThread, NULL);
//======================================================
// PERSISTENT STORAGE INITIALIZATION
//======================================================
readPersistentStorage();
pthread_t persistentThread;
pthread_create(&persistentThread, NULL, persistentStorage, NULL);
//======================================================
// MAIN LOOP
//======================================================
struct timespec timer_start;
for(;;)
{
clock_gettime(CLOCK_MONOTONIC, &timer_start);
@ -85,6 +103,7 @@ int main(void)
while (measureTime(&timer_start) < OPLC_CYCLE)
{
updateBuffers();
sleep_thread(1);
}
}
}

107
core/persistent_storage.cpp Normal file
View File

@ -0,0 +1,107 @@
//-----------------------------------------------------------------------------
// Copyright 2015 Thiago Alves
// This file is part of the OpenPLC Software Stack.
//
// OpenPLC is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenPLC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with OpenPLC. If not, see <http://www.gnu.org/licenses/>.
//------
//
// This file is responsible for the persistent storage on the OpenPLC
// Thiago Alves, Mar 2016
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include "ladder.h"
//-----------------------------------------------------------------------------
// Main function for the thread. Should create a buffer for the persistent
// data, compare it with the actual data and write back to the persistent
// file if the data has changed
//-----------------------------------------------------------------------------
void *persistentStorage(void *args)
{
SWORD persistentBuffer[BUFFER_SIZE];
pthread_mutex_lock(&bufferLock); //lock mutex
for (int i = 0; i < BUFFER_SIZE; i++)
{
persistentBuffer[i] = AnalogOutputBuffer0[i];
}
pthread_mutex_unlock(&bufferLock); //unlock mutex
while (1)
{
//printf("checking data...\n");
bool bufferOutdated = false;
pthread_mutex_lock(&bufferLock); //lock mutex
for (int i = 0; i < BUFFER_SIZE; i++)
{
if (persistentBuffer[i] != AnalogOutputBuffer0[i])
{
persistentBuffer[i] = AnalogOutputBuffer0[i];
bufferOutdated = true;
}
}
pthread_mutex_unlock(&bufferLock); //unlock mutex
if (bufferOutdated)
{
//printf("writing data to disk...\n");
FILE *fd = fopen("persistent.file", "w"); //if file already exists, it will be overwritten
if (fd == NULL)
{
printf("Error creating persistent memory file!\n");
return 0;
}
if (fwrite(persistentBuffer, sizeof(SWORD), BUFFER_SIZE, fd) < BUFFER_SIZE)
{
printf("Error writing to persistent memory file!\n");
return 0;
}
fclose(fd);
}
sleep_thread(1000);
}
}
int readPersistentStorage()
{
FILE *fd = fopen("persistent.file", "r");
if (fd == NULL)
{
printf("Error openning persistent memory file, or file doesn't exists!\n");
return 0;
}
SWORD persistentBuffer[BUFFER_SIZE];
if (fread(persistentBuffer, sizeof(SWORD), BUFFER_SIZE, fd) < BUFFER_SIZE)
{
printf("Error while trying to read the persistent memory file!\n");
return 0;
}
fclose(fd);
pthread_mutex_lock(&bufferLock); //lock mutex
for (int i = 0; i < BUFFER_SIZE; i++)
{
AnalogOutputBuffer0[i] = persistentBuffer[i];
}
pthread_mutex_unlock(&bufferLock); //unlock mutex
}