#include "plsr_resource.h" #include "plsr_address_map.h" #include #ifndef PLSR_HOST_TEST #include "stm32f4xx.h" #endif #define PLSR_HIGH_OUTPUT_MASK (0x0000000FUL) #define PLSR_VALID_OUTPUT_MASK (0x0013FCFFUL) #define PLSR_OUTPUT_POINT_COUNT (21U) #define PLSR_RESOURCE_OWNER_NONE (0xFFU) static uint32_t PlsrUsedOutputMask; static uint8_t PlsrUsedHighMask; static uint8_t PlsrOutputOwners[PLSR_OUTPUT_POINT_COUNT]; static uint32_t PlsrResourceEnterCritical(void) { #ifdef PLSR_HOST_TEST return 0UL; #else uint32_t interruptState = __get_PRIMASK(); __disable_irq(); __DMB(); return interruptState; #endif } static void PlsrResourceExitCritical(uint32_t interruptState) { #ifdef PLSR_HOST_TEST (void)interruptState; #else __DMB(); if (interruptState == 0UL) { __enable_irq(); } #endif } static uint8_t PlsrResourceOutputPointIsValid(uint8_t point) { if (point >= PLSR_OUTPUT_POINT_COUNT) { return 0U; } return ((PLSR_VALID_OUTPUT_MASK & (1UL << point)) != 0UL) ? 1U : 0U; } void PlsrResourceInit(void) { uint32_t interruptState = PlsrResourceEnterCritical(); PlsrUsedOutputMask = 0UL; PlsrUsedHighMask = 0U; (void)memset(PlsrOutputOwners, PLSR_RESOURCE_OWNER_NONE, sizeof(PlsrOutputOwners)); PlsrResourceExitCritical(interruptState); } PLSR_RESULT PlsrResourceReserve(const PLSR_RESOURCE_REQUEST *request, PLSR_RESOURCE_LEASE *lease) { uint32_t requestedOutputMask; uint32_t interruptState; uint8_t requestedHighMask; uint8_t point; if ((request == NULL) || (lease == NULL)) { return PLSR_RESULT_INVALID_ARGUMENT; } if ((request->ownerAxis >= PLSR_AXIS_COUNT) || (request->dAxis >= PLSR_AXIS_COUNT) || (request->ownerAxis != request->dAxis)) { return PLSR_RESULT_INVALID_AXIS; } if (lease->valid != 0U) { return PLSR_RESULT_BUSY; } if (request->outputMode == PLSR_OUTPUT_PULSE_DIR) { if ((PlsrResourceOutputPointIsValid(request->directionPoint) == 0U) || (request->directionPoint == request->dAxis)) { return PLSR_RESULT_INVALID_RESOURCE; } requestedHighMask = (uint8_t)(1U << request->dAxis); requestedOutputMask = (uint32_t)requestedHighMask | (1UL << request->directionPoint); } else if ((request->outputMode == PLSR_OUTPUT_AB) || (request->outputMode == PLSR_OUTPUT_CW_CCW)) { if ((request->dAxis != 0U) && (request->dAxis != 2U)) { return PLSR_RESULT_INVALID_RESOURCE; } requestedHighMask = (uint8_t)(0x03U << request->dAxis); requestedOutputMask = (uint32_t)requestedHighMask; } else { return PLSR_RESULT_INVALID_RESOURCE; } interruptState = PlsrResourceEnterCritical(); if ((PlsrUsedOutputMask & requestedOutputMask) != 0UL) { PlsrResourceExitCritical(interruptState); return PLSR_RESULT_RESOURCE_CONFLICT; } PlsrUsedOutputMask |= requestedOutputMask; PlsrUsedHighMask |= requestedHighMask; for (point = 0U; point < PLSR_OUTPUT_POINT_COUNT; point++) { if ((requestedOutputMask & (1UL << point)) != 0UL) { PlsrOutputOwners[point] = request->ownerAxis; } } PlsrResourceExitCritical(interruptState); lease->outputMask = requestedOutputMask; lease->highMask = requestedHighMask; lease->ownerAxis = request->ownerAxis; lease->directionPoint = (request->outputMode == PLSR_OUTPUT_PULSE_DIR) ? request->directionPoint : PLSR_DIRECTION_POINT_NONE; lease->outputMode = request->outputMode; lease->valid = 1U; return PLSR_RESULT_OK; } void PlsrResourceRelease(PLSR_RESOURCE_LEASE *lease) { uint32_t releaseMask = 0UL; uint32_t interruptState; uint8_t point; if ((lease == NULL) || (lease->valid == 0U)) { return; } interruptState = PlsrResourceEnterCritical(); for (point = 0U; point < PLSR_OUTPUT_POINT_COUNT; point++) { if (((lease->outputMask & (1UL << point)) != 0UL) && (PlsrOutputOwners[point] == lease->ownerAxis)) { releaseMask |= (1UL << point); PlsrOutputOwners[point] = PLSR_RESOURCE_OWNER_NONE; } } PlsrUsedOutputMask &= ~releaseMask; PlsrUsedHighMask = (uint8_t)(PlsrUsedOutputMask & PLSR_HIGH_OUTPUT_MASK); PlsrResourceExitCritical(interruptState); (void)memset(lease, 0, sizeof(*lease)); lease->directionPoint = PLSR_DIRECTION_POINT_NONE; } void PlsrResourceGetStatus(PLSR_RESOURCE_STATUS *status) { uint32_t interruptState; if (status == NULL) { return; } interruptState = PlsrResourceEnterCritical(); status->outputMask = PlsrUsedOutputMask; status->highMask = PlsrUsedHighMask; PlsrResourceExitCritical(interruptState); } uint8_t PlsrResourceCheckInvariant(void) { uint32_t interruptState; uint8_t valid = 1U; uint8_t point; interruptState = PlsrResourceEnterCritical(); if (PlsrUsedHighMask != (uint8_t)(PlsrUsedOutputMask & PLSR_HIGH_OUTPUT_MASK)) { valid = 0U; } for (point = 0U; point < PLSR_OUTPUT_POINT_COUNT; point++) { if (((PlsrUsedOutputMask & (1UL << point)) == 0UL) != (PlsrOutputOwners[point] == PLSR_RESOURCE_OWNER_NONE)) { valid = 0U; } } PlsrResourceExitCritical(interruptState); return valid; }