mirror of
https://github.com/thiagoralves/OpenPLC.git
synced 2025-05-09 16:42:00 +08:00
Added persistent storage to the OpenPLC! :)
This commit is contained in:
parent
5dbfec2d80
commit
b67eea7c13
@ -56,10 +56,10 @@ extern pthread_mutex_t bufferLock;
|
|||||||
|
|
||||||
//hardware_layer.cpp
|
//hardware_layer.cpp
|
||||||
void initializeHardware();
|
void initializeHardware();
|
||||||
void sendOutput(unsigned char *sendBytes, unsigned char *recvBytes);
|
|
||||||
void updateBuffers();
|
void updateBuffers();
|
||||||
|
|
||||||
//openplc.cpp
|
//openplc.cpp
|
||||||
|
void sleep_thread(int milliseconds);
|
||||||
void *modbusThread();
|
void *modbusThread();
|
||||||
void PlcCycle(void); //read inputs, process them according to the ladder software and set outputs
|
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 *handleConnections(void *arguments);
|
||||||
void startServer(int port);
|
void startServer(int port);
|
||||||
|
|
||||||
|
//persistent_storage.cpp
|
||||||
|
void *persistentStorage(void *args);
|
||||||
|
int readPersistentStorage();
|
||||||
|
|
||||||
//modbus.cpp
|
//modbus.cpp
|
||||||
//Declaration of the supported modbus functions and the respective function code
|
//Declaration of the supported modbus functions and the respective function code
|
||||||
enum MB_FC
|
enum MB_FC
|
||||||
|
@ -34,6 +34,18 @@ using namespace std;
|
|||||||
pthread_mutex_t bufferLock; //mutex for the internal buffers
|
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)
|
void *modbusThread(void *arg)
|
||||||
{
|
{
|
||||||
startServer(502);
|
startServer(502);
|
||||||
@ -70,14 +82,20 @@ int main(void)
|
|||||||
//======================================================
|
//======================================================
|
||||||
initializeHardware();
|
initializeHardware();
|
||||||
updateBuffers();
|
updateBuffers();
|
||||||
|
|
||||||
struct timespec timer_start;
|
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
pthread_create(&thread, NULL, modbusThread, NULL);
|
pthread_create(&thread, NULL, modbusThread, NULL);
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// PERSISTENT STORAGE INITIALIZATION
|
||||||
|
//======================================================
|
||||||
|
readPersistentStorage();
|
||||||
|
pthread_t persistentThread;
|
||||||
|
pthread_create(&persistentThread, NULL, persistentStorage, NULL);
|
||||||
|
|
||||||
//======================================================
|
//======================================================
|
||||||
// MAIN LOOP
|
// MAIN LOOP
|
||||||
//======================================================
|
//======================================================
|
||||||
|
struct timespec timer_start;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
clock_gettime(CLOCK_MONOTONIC, &timer_start);
|
clock_gettime(CLOCK_MONOTONIC, &timer_start);
|
||||||
@ -85,6 +103,7 @@ int main(void)
|
|||||||
while (measureTime(&timer_start) < OPLC_CYCLE)
|
while (measureTime(&timer_start) < OPLC_CYCLE)
|
||||||
{
|
{
|
||||||
updateBuffers();
|
updateBuffers();
|
||||||
|
sleep_thread(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
107
core/persistent_storage.cpp
Normal file
107
core/persistent_storage.cpp
Normal 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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user