Files
hsb/S - Software/0 - HSB MRTS Kathode-MCP/3 - Implementation/0 - Code/HAL/src/Interlock.c
2017-10-25 14:50:20 +00:00

169 lines
4.8 KiB
C

// -----------------------------------------------------------------------------
/// @file Interlock.c
/// @brief Description
// -----------------------------------------------------------------------------
// Micro-Key bv
// Industrieweg 28, 9804 TG Noordhorn
// Postbus 92, 9800 AB Zuidhorn
// The Netherlands
// Tel: +31 594 503020
// Fax: +31 594 505825
// Email: support@microkey.nl
// Web: www.microkey.nl
// -----------------------------------------------------------------------------
/// $Revision$
/// $Author$
/// $Date$
// (c) 2017 Micro-Key bv
// -----------------------------------------------------------------------------
/// @file Interlock.c
/// @ingroup {group_name}
// -----------------------------------------------------------------------------
// Include files
// -----------------------------------------------------------------------------
#include "stm32f10x.h"
#include "Error.h"
#include "Logger.h"
#include "Interlock.h"
// -----------------------------------------------------------------------------
// Constant and macro definitions
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Type definitions
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// File-scope variables
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Function declarations
// -----------------------------------------------------------------------------
static void InterlockTask (void* parameters);
// -----------------------------------------------------------------------------
// Function definitions
// -----------------------------------------------------------------------------
ErrorStatus Interlock_construct(struct Interlock* self, T_INTERLOCK_ID ID, struct Gpio* NO, EXTI_InitTypeDef NOEXTI, struct Gpio* NC, EXTI_InitTypeDef NCEXTI, int waitToDebounce_ms)
{
ErrorStatus returnValue = SUCCESS;
if (!self->initialized)
{
vSemaphoreCreateBinary(self->semaphore);
xSemaphoreTake(self->semaphore, 0);
BaseType_t rv = xTaskCreate(InterlockTask, (const char*)"InterlockIO", 300, self, 1, &self->taskHandle);
if (rv != pdTRUE)
{
returnValue = ERROR;
LOGGER_ERROR(mainLog, "FAILED to start Interlock ID %d with code %d", ID, (int)rv);
}
else
{
self->ID = ID;
self->NO.io = NO;
self->NO.ioEXTI = NOEXTI;
self->NC.io = NC;
self->NC.ioEXTI = NCEXTI;
self->waitToDebounce_ms = waitToDebounce_ms;
self->initialized = true;
LOGGER_INFO(mainLog, "Interlock ID %d started", self->ID);
}
}
else
{
returnValue = ERROR;
}
return returnValue;
}
void Interlock_getStatus(struct Interlock* self, FunctionalState* command, int* NO, int* NC)
{
*command = self->NO.ioEXTI.EXTI_LineCmd;
size_t actualLength;
IODevice_read((struct IODevice*)self->NO.io, (char*)NO, 1, &actualLength);
IODevice_read((struct IODevice*)self->NC.io, (char*)NC, 1, &actualLength);
}
bool Interlock_isClosed(struct Interlock* self)
{
bool returnValue;
char no;
char nc;
size_t actualLength;
IODevice_read((struct IODevice*)self->NO.io, &no, 1, &actualLength);
IODevice_read((struct IODevice*)self->NC.io, &nc, 1, &actualLength);
if ((nc != 0) && (no == 0))
{
returnValue = true;
}
else
{
returnValue = false;
}
return returnValue;
}
void Interlock_setEXTI(struct Interlock* self, FunctionalState command)
{
self->NO.ioEXTI.EXTI_LineCmd = command;
EXTI_Init(&self->NO.ioEXTI);
self->NC.ioEXTI.EXTI_LineCmd = command;
EXTI_Init(&self->NC.ioEXTI);
}
static void InterlockTask (void* parameters)
{
struct Interlock* self = (struct Interlock*)parameters;
while(1)
{
// Interlock was OK when the IRQ became active
// This tasks debounces the Interlock against accidental detections
// THe semaphore is given from ISR
xSemaphoreTake(self->semaphore, portMAX_DELAY);
// Wait for the debounce time
vTaskDelay(self->waitToDebounce_ms);
// Check if the Interrupt was justified
if (!Interlock_isClosed(self))
{
// The Interlock is open, so the Interrupt was justified
if (self->ID == COMMON_INTERLOCK)
{
Error_postError(INTERLOCK_COMMON_FAIL);
}
}
else
{
// False alarm
}
}
}