// ----------------------------------------------------------------------------- /// @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 } } }