|
- #include "plsr_platform.h"
- #include "plsr.h"
-
- #ifdef PLSR_HOST_TEST
-
- #include <string.h>
-
- static uint8_t PlsrHostPulseActive[4];
- static uint32_t PlsrHostFrequency[4];
- static uint32_t PlsrHostQueuedFrequency[4];
- static uint8_t PlsrHostUpdatePending[4];
- static uint8_t PlsrHostInputs[2];
- static uint8_t PlsrHostSelectedPulse;
- static uint8_t PlsrHostDirectionLevel;
- static uint8_t PlsrHostEmitPulseOnCriticalEntry;
- static uint8_t PlsrHostEmitPulseOnCriticalExit;
- static uint8_t PlsrHostLatchPulseOnCriticalEntry;
- static uint8_t PlsrHostCriticalEntriesToSkip;
- static uint8_t PlsrHostFailNextStart;
- static uint8_t PlsrHostFailNextFrequencyAtUpdate;
- static PLSR_PERSIST_PAYLOAD PlsrHostPersistentPayload;
- static uint8_t PlsrHostPersistentValid;
- static uint32_t PlsrHostSaveCount;
-
- static void PlsrHostLatchPulse(uint8_t pulseOutput)
- {
- if ((pulseOutput <= 3U)
- && (PlsrHostPulseActive[pulseOutput] != 0U))
- {
- PlsrHostFrequency[pulseOutput] =
- PlsrHostQueuedFrequency[pulseOutput];
- PlsrHostUpdatePending[pulseOutput] = 1U;
- }
- }
-
- static void PlsrHostServicePendingPulse(uint8_t pulseOutput)
- {
- if ((pulseOutput <= 3U)
- && (PlsrHostUpdatePending[pulseOutput] != 0U))
- {
- PlsrHostUpdatePending[pulseOutput] = 0U;
- PlsrPulseTimerIrq(pulseOutput);
- }
- }
-
- uint8_t PlsrPlatformInit(void)
- {
- (void)memset(PlsrHostPulseActive, 0, sizeof(PlsrHostPulseActive));
- (void)memset(PlsrHostFrequency, 0, sizeof(PlsrHostFrequency));
- (void)memset(PlsrHostQueuedFrequency, 0,
- sizeof(PlsrHostQueuedFrequency));
- (void)memset(PlsrHostUpdatePending, 0,
- sizeof(PlsrHostUpdatePending));
- PlsrHostSelectedPulse = 0U;
- PlsrHostDirectionLevel = 0U;
- PlsrHostEmitPulseOnCriticalEntry = 0U;
- PlsrHostEmitPulseOnCriticalExit = 0U;
- PlsrHostLatchPulseOnCriticalEntry = 0U;
- PlsrHostCriticalEntriesToSkip = 0U;
- PlsrHostFailNextStart = 0U;
- PlsrHostFailNextFrequencyAtUpdate = 0U;
- return 1U;
- }
-
- uint8_t PlsrPlatformPrepare(uint8_t pulseOutput,
- uint8_t directionOutput,
- uint8_t directionLevel)
- {
- uint8_t index;
- (void)directionOutput;
-
- if (PlsrHostFailNextStart != 0U)
- {
- PlsrHostFailNextStart = 0U;
- return 0U;
- }
- if ((pulseOutput > 3U) || (directionOutput > 3U))
- {
- return 0U;
- }
- for (index = 0U; index < 4U; index++)
- {
- PlsrHostPulseActive[index] = 0U;
- PlsrHostFrequency[index] = 0UL;
- PlsrHostQueuedFrequency[index] = 0UL;
- PlsrHostUpdatePending[index] = 0U;
- }
- PlsrHostSelectedPulse = pulseOutput;
- PlsrHostDirectionLevel = (directionLevel != 0U) ? 1U : 0U;
- return 1U;
- }
-
- uint8_t PlsrPlatformStartPulse(uint8_t pulseOutput,
- uint32_t firstFrequencyHz,
- uint32_t queuedFrequencyHz,
- uint32_t *actualFirstFrequencyHz,
- uint32_t *actualQueuedFrequencyHz)
- {
- if ((pulseOutput > 3U) || (firstFrequencyHz == 0UL)
- || (firstFrequencyHz > PLSR_FREQUENCY_MAX_HZ)
- || (queuedFrequencyHz == 0UL)
- || (queuedFrequencyHz > PLSR_FREQUENCY_MAX_HZ)
- || (actualFirstFrequencyHz == NULL)
- || (actualQueuedFrequencyHz == NULL))
- {
- return 0U;
- }
- PlsrHostPulseActive[pulseOutput] = 1U;
- PlsrHostFrequency[pulseOutput] = firstFrequencyHz;
- PlsrHostQueuedFrequency[pulseOutput] = queuedFrequencyHz;
- PlsrHostUpdatePending[pulseOutput] = 0U;
- PlsrHostSelectedPulse = pulseOutput;
- *actualFirstFrequencyHz = firstFrequencyHz;
- *actualQueuedFrequencyHz = queuedFrequencyHz;
- return 1U;
- }
-
- uint8_t PlsrPlatformQueueFrequency(uint8_t pulseOutput,
- uint32_t frequencyHz,
- uint32_t *actualFrequencyHz)
- {
- if (PlsrHostFailNextFrequencyAtUpdate != 0U)
- {
- PlsrHostFailNextFrequencyAtUpdate = 0U;
- return 0U;
- }
- if ((pulseOutput > 3U) || (frequencyHz == 0UL)
- || (frequencyHz > PLSR_FREQUENCY_MAX_HZ)
- || (actualFrequencyHz == NULL)
- || (PlsrHostPulseActive[pulseOutput] == 0U))
- {
- return 0U;
- }
- PlsrHostQueuedFrequency[pulseOutput] = frequencyHz;
- *actualFrequencyHz = frequencyHz;
- return 1U;
- }
-
- void PlsrPlatformDrainPendingPulse(uint8_t pulseOutput)
- {
- PlsrHostServicePendingPulse(pulseOutput);
- }
-
- uint32_t PlsrPlatformActiveFrequency(uint8_t pulseOutput)
- {
- return (pulseOutput <= 3U) ? PlsrHostFrequency[pulseOutput] : 0UL;
- }
-
- void PlsrPlatformStopPulse(uint8_t pulseOutput)
- {
- if (pulseOutput <= 3U)
- {
- PlsrHostPulseActive[pulseOutput] = 0U;
- PlsrHostFrequency[pulseOutput] = 0UL;
- PlsrHostQueuedFrequency[pulseOutput] = 0UL;
- PlsrHostUpdatePending[pulseOutput] = 0U;
- }
- }
-
- uint8_t PlsrPlatformReadInput(uint8_t inputSelection)
- {
- return (inputSelection <= 1U) ? PlsrHostInputs[inputSelection] : 0U;
- }
-
- uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload)
- {
- if ((payload == NULL) || (PlsrHostPersistentValid == 0U))
- {
- return 0U;
- }
- *payload = PlsrHostPersistentPayload;
- return 1U;
- }
-
- uint8_t PlsrPlatformSave(const PLSR_PERSIST_PAYLOAD *payload)
- {
- if (payload == NULL)
- {
- return 0U;
- }
- PlsrHostPersistentPayload = *payload;
- PlsrHostPersistentValid = 1U;
- PlsrHostSaveCount++;
- return 1U;
- }
-
- void PlsrPlatformCheckpointConfig(const PLSR_CONFIG *config)
- {
- if (config != NULL)
- {
- PlsrHostPersistentPayload.config = *config;
- PlsrHostPersistentValid = 1U;
- }
- }
-
- void PlsrPlatformCheckpointPosition(int32_t position,
- uint8_t positionValid,
- uint8_t wasBusy)
- {
- PlsrHostPersistentPayload.position = position;
- PlsrHostPersistentPayload.positionValid = positionValid;
- PlsrHostPersistentPayload.wasBusy = wasBusy;
- PlsrHostPersistentPayload.reserved = 0U;
- }
-
- uint32_t PlsrPlatformEnterCritical(void)
- {
- if (PlsrHostEmitPulseOnCriticalEntry != 0U)
- {
- if (PlsrHostCriticalEntriesToSkip != 0U)
- {
- PlsrHostCriticalEntriesToSkip--;
- }
- else
- {
- PlsrHostEmitPulseOnCriticalEntry = 0U;
- PlsrHostLatchPulse(PlsrHostSelectedPulse);
- PlsrHostServicePendingPulse(PlsrHostSelectedPulse);
- }
- }
- if (PlsrHostLatchPulseOnCriticalEntry != 0U)
- {
- PlsrHostLatchPulseOnCriticalEntry = 0U;
- PlsrHostLatchPulse(PlsrHostSelectedPulse);
- }
- return 0UL;
- }
-
- void PlsrPlatformExitCritical(uint32_t state)
- {
- (void)state;
- if (PlsrHostEmitPulseOnCriticalExit != 0U)
- {
- PlsrHostEmitPulseOnCriticalExit = 0U;
- PlsrHostLatchPulse(PlsrHostSelectedPulse);
- }
- PlsrHostServicePendingPulse(PlsrHostSelectedPulse);
- }
-
- void PlsrTestSetInput(uint8_t inputSelection, uint8_t level)
- {
- if (inputSelection <= 1U)
- {
- PlsrHostInputs[inputSelection] = (level != 0U) ? 1U : 0U;
- }
- }
-
- void PlsrTestEmitPulses(uint32_t pulseCount)
- {
- while ((pulseCount != 0UL)
- && (PlsrHostPulseActive[PlsrHostSelectedPulse] != 0U))
- {
- PlsrHostLatchPulse(PlsrHostSelectedPulse);
- PlsrHostServicePendingPulse(PlsrHostSelectedPulse);
- pulseCount--;
- }
- }
-
- void PlsrTestEmitPulseOnCriticalEntry(void)
- {
- PlsrHostCriticalEntriesToSkip = 0U;
- PlsrHostEmitPulseOnCriticalEntry = 1U;
- }
-
- void PlsrTestEmitPulseAfterCriticalEntries(uint8_t entriesToSkip)
- {
- PlsrHostCriticalEntriesToSkip = entriesToSkip;
- PlsrHostEmitPulseOnCriticalEntry = 1U;
- }
-
- void PlsrTestEmitPulseOnCriticalExit(void)
- {
- PlsrHostEmitPulseOnCriticalExit = 1U;
- }
-
- void PlsrTestLatchPulseOnCriticalEntry(void)
- {
- PlsrHostLatchPulseOnCriticalEntry = 1U;
- }
-
- void PlsrTestServicePendingPulse(void)
- {
- PlsrHostServicePendingPulse(PlsrHostSelectedPulse);
- }
-
- void PlsrTestFailNextStart(void)
- {
- PlsrHostFailNextStart = 1U;
- }
-
- void PlsrTestFailNextFrequencyAtUpdate(void)
- {
- PlsrHostFailNextFrequencyAtUpdate = 1U;
- }
-
- uint8_t PlsrTestPulseIsActive(void)
- {
- return PlsrHostPulseActive[PlsrHostSelectedPulse];
- }
-
- uint32_t PlsrTestOutputFrequency(void)
- {
- return PlsrHostFrequency[PlsrHostSelectedPulse];
- }
-
- uint32_t PlsrTestQueuedFrequency(void)
- {
- return PlsrHostQueuedFrequency[PlsrHostSelectedPulse];
- }
-
- uint8_t PlsrTestDirectionLevel(void)
- {
- return PlsrHostDirectionLevel;
- }
-
- void PlsrTestClearPersistentStorage(void)
- {
- (void)memset(&PlsrHostPersistentPayload, 0,
- sizeof(PlsrHostPersistentPayload));
- (void)memset(PlsrHostInputs, 0, sizeof(PlsrHostInputs));
- PlsrHostPersistentValid = 0U;
- PlsrHostSaveCount = 0UL;
- }
-
- void PlsrTestResetSaveCount(void)
- {
- PlsrHostSaveCount = 0UL;
- }
-
- uint32_t PlsrTestSaveCount(void)
- {
- return PlsrHostSaveCount;
- }
-
- #else
-
- #include "stm32f4xx_hal.h"
- #include <stddef.h>
- #include <string.h>
-
- #define PLSR_ENABLE_IRQ_CYCLE_DIAG (0U)
-
- #define PLSR_FLASH_SLOT_A_ADDRESS (0x080C0000UL)
- #define PLSR_FLASH_SLOT_B_ADDRESS (0x080E0000UL)
- #define PLSR_FLASH_MAGIC (0x50534C52UL)
- #define PLSR_FLASH_VERSION (2U)
- #define PLSR_BACKUP_CONFIG_ADDRESS (BKPSRAM_BASE + 0x0100UL)
- #define PLSR_BACKUP_POSITION_ADDRESS (BKPSRAM_BASE + 0x0200UL)
- #define PLSR_BACKUP_CONFIG_MAGIC (0x50434647UL)
- #define PLSR_BACKUP_POSITION_MAGIC (0x50504F53UL)
-
- typedef struct
- {
- TIM_TypeDef *timer;
- GPIO_TypeDef *port;
- uint16_t pin;
- uint8_t pinIndex;
- uint8_t alternate;
- IRQn_Type irq;
- uint32_t timerClockHz;
- } PLSR_TIMER_MAP;
-
- typedef struct
- {
- GPIO_TypeDef *port;
- uint16_t pin;
- } PLSR_GPIO_MAP;
-
- typedef struct
- {
- uint32_t prescaler;
- uint32_t period;
- uint32_t compare;
- uint32_t actualFrequencyHz;
- } PLSR_TIMER_SETTING;
-
- typedef struct
- {
- uint32_t magic;
- uint16_t version;
- uint16_t payloadSize;
- uint32_t generation;
- PLSR_PERSIST_PAYLOAD payload;
- uint32_t crc32;
- } PLSR_FLASH_RECORD;
-
- typedef struct
- {
- uint32_t magic;
- PLSR_CONFIG config;
- uint32_t crc32;
- } PLSR_BACKUP_CONFIG_RECORD;
-
- typedef struct
- {
- uint32_t magic;
- uint32_t generation;
- int32_t position;
- uint8_t positionValid;
- uint8_t wasBusy;
- uint16_t reserved;
- uint32_t crc32;
- } PLSR_BACKUP_POSITION_RECORD;
-
- static const PLSR_TIMER_MAP PlsrTimerMap[4] =
- {
- {TIM10, GPIOF, GPIO_PIN_6, 6U, GPIO_AF3_TIM10,
- TIM1_UP_TIM10_IRQn, 168000000UL},
- {TIM13, GPIOF, GPIO_PIN_8, 8U, GPIO_AF9_TIM13,
- TIM8_UP_TIM13_IRQn, 84000000UL},
- {TIM11, GPIOF, GPIO_PIN_7, 7U, GPIO_AF3_TIM11,
- TIM1_TRG_COM_TIM11_IRQn, 168000000UL},
- {TIM14, GPIOF, GPIO_PIN_9, 9U, GPIO_AF9_TIM14,
- TIM8_TRG_COM_TIM14_IRQn, 84000000UL}
- };
-
- static const PLSR_GPIO_MAP PlsrDirectionMap[4] =
- {
- {GPIOH, GPIO_PIN_9},
- {GPIOH, GPIO_PIN_8},
- {GPIOH, GPIO_PIN_7},
- {GPIOH, GPIO_PIN_6}
- };
-
- static PLSR_FLASH_RECORD PlsrFlashRecordBuffer;
- static uint32_t PlsrBackupPositionGeneration;
- static uint32_t PlsrTimerActiveFrequencyHz[4];
- static uint32_t PlsrTimerQueuedFrequencyHz[4];
- static uint32_t PlsrTimerQueueGeneration[4];
-
- static void PlsrHandleTimerIrq(uint8_t pulseOutput);
-
- #if PLSR_ENABLE_IRQ_CYCLE_DIAG
- volatile uint32_t PlsrIrqCount[4];
- volatile uint32_t PlsrIrqLastCycles[4];
- volatile uint32_t PlsrIrqMaxCycles[4];
- #endif
-
- static uint32_t PlsrCrc32(const void *data, uint32_t length)
- {
- const uint8_t *bytes = (const uint8_t *)data;
- uint32_t crc = 0xFFFFFFFFUL;
- uint32_t index;
- uint8_t bit;
-
- for (index = 0UL; index < length; index++)
- {
- crc ^= bytes[index];
- for (bit = 0U; bit < 8U; bit++)
- {
- crc = ((crc & 1UL) != 0UL) ? ((crc >> 1U) ^ 0xEDB88320UL)
- : (crc >> 1U);
- }
- }
- return ~crc;
- }
-
- static uint8_t PlsrGenerationIsNewer(uint32_t first, uint32_t second)
- {
- return ((int32_t)(first - second) > 0) ? 1U : 0U;
- }
-
- static uint32_t PlsrFlashRecordCrc(const PLSR_FLASH_RECORD *record)
- {
- const uint8_t *start = (const uint8_t *)&record->version;
- uint32_t length = (uint32_t)(offsetof(PLSR_FLASH_RECORD, crc32)
- - offsetof(PLSR_FLASH_RECORD, version));
- return PlsrCrc32(start, length);
- }
-
- static uint8_t PlsrFlashRecordIsValid(const PLSR_FLASH_RECORD *record)
- {
- return ((record->magic == PLSR_FLASH_MAGIC)
- && (record->version == PLSR_FLASH_VERSION)
- && (record->payloadSize == sizeof(PLSR_PERSIST_PAYLOAD))
- && (record->crc32 == PlsrFlashRecordCrc(record))) ? 1U : 0U;
- }
-
- static uint8_t PlsrBackupConfigIsValid(
- const PLSR_BACKUP_CONFIG_RECORD *record)
- {
- return ((record->magic == PLSR_BACKUP_CONFIG_MAGIC)
- && (record->crc32
- == PlsrCrc32(&record->config, sizeof(record->config)))) ? 1U : 0U;
- }
-
- static uint8_t PlsrBackupPositionIsValid(
- const PLSR_BACKUP_POSITION_RECORD *record)
- {
- uint32_t crc = PlsrCrc32(&record->generation,
- sizeof(record->generation)
- + sizeof(record->position)
- + sizeof(record->positionValid)
- + sizeof(record->wasBusy)
- + sizeof(record->reserved));
- return ((record->magic == PLSR_BACKUP_POSITION_MAGIC)
- && (record->crc32 == crc)) ? 1U : 0U;
- }
-
- static const PLSR_BACKUP_POSITION_RECORD *PlsrNewestBackupPosition(void)
- {
- const PLSR_BACKUP_POSITION_RECORD *slots =
- (const PLSR_BACKUP_POSITION_RECORD *)PLSR_BACKUP_POSITION_ADDRESS;
- uint8_t validA = PlsrBackupPositionIsValid(&slots[0]);
- uint8_t validB = PlsrBackupPositionIsValid(&slots[1]);
-
- if ((validA == 0U) && (validB == 0U))
- {
- return NULL;
- }
- if (validA == 0U)
- {
- return &slots[1];
- }
- if (validB == 0U)
- {
- return &slots[0];
- }
- return (PlsrGenerationIsNewer(slots[1].generation,
- slots[0].generation) != 0U)
- ? &slots[1] : &slots[0];
- }
-
- static void PlsrTimerStop(TIM_TypeDef *timer)
- {
- timer->DIER &= ~TIM_DIER_UIE;
- timer->CR1 &= ~TIM_CR1_CEN;
- timer->CCER &= ~TIM_CCER_CC1E;
- timer->SR = ~TIM_SR_UIF;
- }
-
- static void PlsrTimerInitialize(TIM_TypeDef *timer)
- {
- timer->CR1 = TIM_CR1_ARPE | TIM_CR1_URS;
- timer->CR2 = 0UL;
- timer->SMCR = 0UL;
- timer->DIER = 0UL;
- timer->CCMR1 = TIM_CCMR1_OC1PE | (6UL << TIM_CCMR1_OC1M_Pos);
- timer->CCER = 0UL;
- timer->PSC = 0UL;
- timer->ARR = 999UL;
- timer->CCR1 = 500UL;
- timer->CNT = 0UL;
- timer->EGR = TIM_EGR_UG;
- timer->SR = 0UL;
- }
-
- static void PlsrPulsePinHoldIdle(uint8_t pulseOutput)
- {
- const PLSR_TIMER_MAP *map = &PlsrTimerMap[pulseOutput];
- GPIO_InitTypeDef gpio;
-
- HAL_GPIO_WritePin(map->port, map->pin, GPIO_PIN_SET);
- gpio.Pin = map->pin;
- gpio.Mode = GPIO_MODE_OUTPUT_PP;
- gpio.Pull = GPIO_NOPULL;
- gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- gpio.Alternate = 0U;
- HAL_GPIO_Init(map->port, &gpio);
- }
-
- static void PlsrPulsePinCaptureIdle(uint8_t pulseOutput)
- {
- const PLSR_TIMER_MAP *map = &PlsrTimerMap[pulseOutput];
- uint32_t shift = (uint32_t)map->pinIndex * 2UL;
- uint32_t mode = map->port->MODER;
-
- /* The update IRQ occurs while PWM is high; switch to GPIO high first. */
- map->port->BSRR = map->pin;
- mode &= ~(3UL << shift);
- mode |= 1UL << shift;
- map->port->MODER = mode;
- __DSB();
- }
-
- static void PlsrPulsePinRelease(uint8_t pulseOutput)
- {
- const PLSR_TIMER_MAP *map = &PlsrTimerMap[pulseOutput];
- GPIO_InitTypeDef gpio;
-
- gpio.Pin = map->pin;
- gpio.Mode = GPIO_MODE_AF_PP;
- gpio.Pull = GPIO_NOPULL;
- gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- gpio.Alternate = map->alternate;
- HAL_GPIO_Init(map->port, &gpio);
- __DSB();
- }
-
- static uint8_t PlsrTimerCalculate(uint8_t pulseOutput,
- uint32_t frequencyHz,
- PLSR_TIMER_SETTING *setting)
- {
- const PLSR_TIMER_MAP *map;
- uint32_t prescalerDivider;
- uint32_t denominator;
- uint32_t periodCounts;
-
- if ((pulseOutput > 3U) || (frequencyHz == 0UL)
- || (frequencyHz > PLSR_FREQUENCY_MAX_HZ)
- || (setting == NULL))
- {
- return 0U;
- }
-
- map = &PlsrTimerMap[pulseOutput];
- prescalerDivider = (((map->timerClockHz - 1UL) / frequencyHz) >> 16U)
- + 1UL;
- if (prescalerDivider > 65536UL)
- {
- return 0U;
- }
- denominator = prescalerDivider * frequencyHz;
- periodCounts = (map->timerClockHz + denominator / 2UL) / denominator;
- if (periodCounts < 2UL)
- {
- periodCounts = 2UL;
- }
- if (periodCounts > 65536UL)
- {
- periodCounts = 65536UL;
- }
-
- setting->prescaler = prescalerDivider - 1UL;
- setting->period = periodCounts - 1UL;
- setting->compare = periodCounts / 2UL;
- setting->actualFrequencyHz =
- map->timerClockHz / (prescalerDivider * periodCounts);
- return 1U;
- }
-
- static void PlsrTimerWriteSetting(TIM_TypeDef *timer,
- const PLSR_TIMER_SETTING *setting)
- {
- timer->PSC = setting->prescaler;
- timer->ARR = setting->period;
- timer->CCR1 = setting->compare;
- }
-
- uint8_t PlsrPlatformInit(void)
- {
- GPIO_InitTypeDef gpio;
- uint8_t index;
- const PLSR_BACKUP_POSITION_RECORD *positionRecord;
-
- __HAL_RCC_GPIOB_CLK_ENABLE();
- __HAL_RCC_GPIOF_CLK_ENABLE();
- __HAL_RCC_GPIOG_CLK_ENABLE();
- __HAL_RCC_GPIOH_CLK_ENABLE();
- __HAL_RCC_TIM10_CLK_ENABLE();
- __HAL_RCC_TIM11_CLK_ENABLE();
- __HAL_RCC_TIM13_CLK_ENABLE();
- __HAL_RCC_TIM14_CLK_ENABLE();
- __HAL_RCC_PWR_CLK_ENABLE();
- HAL_PWR_EnableBkUpAccess();
- __HAL_RCC_BKPSRAM_CLK_ENABLE();
- if (HAL_PWREx_EnableBkUpReg() != HAL_OK)
- {
- return 0U;
- }
-
- #if PLSR_ENABLE_IRQ_CYCLE_DIAG
- CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
- DWT->CYCCNT = 0UL;
- DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
- (void)memset((void *)PlsrIrqCount, 0, sizeof(PlsrIrqCount));
- (void)memset((void *)PlsrIrqLastCycles, 0, sizeof(PlsrIrqLastCycles));
- (void)memset((void *)PlsrIrqMaxCycles, 0, sizeof(PlsrIrqMaxCycles));
- #endif
-
- HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8
- | GPIO_PIN_9, GPIO_PIN_SET);
- gpio.Pin = GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9;
- gpio.Mode = GPIO_MODE_OUTPUT_PP;
- gpio.Pull = GPIO_NOPULL;
- gpio.Speed = GPIO_SPEED_FREQ_HIGH;
- gpio.Alternate = 0U;
- HAL_GPIO_Init(GPIOH, &gpio);
-
- gpio.Mode = GPIO_MODE_INPUT;
- gpio.Pull = GPIO_NOPULL;
- gpio.Speed = GPIO_SPEED_FREQ_LOW;
- gpio.Alternate = 0U;
- gpio.Pin = GPIO_PIN_5;
- HAL_GPIO_Init(GPIOB, &gpio);
- gpio.Pin = GPIO_PIN_12;
- HAL_GPIO_Init(GPIOG, &gpio);
-
- for (index = 0U; index < 4U; index++)
- {
- PlsrTimerActiveFrequencyHz[index] = 0UL;
- PlsrTimerQueuedFrequencyHz[index] = 0UL;
- PlsrTimerQueueGeneration[index] = 0UL;
- PlsrTimerInitialize(PlsrTimerMap[index].timer);
- PlsrPulsePinHoldIdle(index);
- HAL_NVIC_SetPriority(PlsrTimerMap[index].irq, 1U, 0U);
- HAL_NVIC_EnableIRQ(PlsrTimerMap[index].irq);
- }
-
- positionRecord = PlsrNewestBackupPosition();
- PlsrBackupPositionGeneration =
- (positionRecord == NULL) ? 0UL : positionRecord->generation;
- return 1U;
- }
-
- uint8_t PlsrPlatformPrepare(uint8_t pulseOutput,
- uint8_t directionOutput,
- uint8_t directionLevel)
- {
- uint8_t index;
-
- if ((pulseOutput > 3U) || (directionOutput > 3U))
- {
- return 0U;
- }
- for (index = 0U; index < 4U; index++)
- {
- PlsrPulsePinHoldIdle(index);
- PlsrTimerStop(PlsrTimerMap[index].timer);
- HAL_GPIO_WritePin(PlsrDirectionMap[index].port,
- PlsrDirectionMap[index].pin,
- GPIO_PIN_SET);
- }
- if (directionLevel != 0U)
- {
- HAL_GPIO_WritePin(PlsrDirectionMap[directionOutput].port,
- PlsrDirectionMap[directionOutput].pin,
- GPIO_PIN_RESET);
- }
- return 1U;
- }
-
- uint8_t PlsrPlatformStartPulse(uint8_t pulseOutput,
- uint32_t firstFrequencyHz,
- uint32_t queuedFrequencyHz,
- uint32_t *actualFirstFrequencyHz,
- uint32_t *actualQueuedFrequencyHz)
- {
- TIM_TypeDef *timer;
- PLSR_TIMER_SETTING firstSetting;
- PLSR_TIMER_SETTING queuedSetting;
-
- if ((actualFirstFrequencyHz == NULL)
- || (actualQueuedFrequencyHz == NULL)
- || (PlsrTimerCalculate(pulseOutput, firstFrequencyHz,
- &firstSetting) == 0U)
- || (PlsrTimerCalculate(pulseOutput, queuedFrequencyHz,
- &queuedSetting) == 0U))
- {
- return 0U;
- }
- timer = PlsrTimerMap[pulseOutput].timer;
- timer->DIER &= ~TIM_DIER_UIE;
- timer->CR1 &= ~TIM_CR1_CEN;
- timer->CCER &= ~TIM_CCER_CC1E;
- timer->CNT = 0UL;
- PlsrTimerWriteSetting(timer, &firstSetting);
- timer->EGR = TIM_EGR_UG;
- PlsrTimerWriteSetting(timer, &queuedSetting);
- timer->SR = 0UL;
- timer->CCER |= TIM_CCER_CC1E;
- __DSB();
- timer->DIER |= TIM_DIER_UIE;
- PlsrPulsePinRelease(pulseOutput);
- timer->CR1 |= TIM_CR1_CEN;
- PlsrTimerActiveFrequencyHz[pulseOutput] =
- firstSetting.actualFrequencyHz;
- PlsrTimerQueuedFrequencyHz[pulseOutput] =
- queuedSetting.actualFrequencyHz;
- PlsrTimerQueueGeneration[pulseOutput]++;
- *actualFirstFrequencyHz = firstSetting.actualFrequencyHz;
- *actualQueuedFrequencyHz = queuedSetting.actualFrequencyHz;
- return 1U;
- }
-
- uint8_t PlsrPlatformQueueFrequency(uint8_t pulseOutput,
- uint32_t frequencyHz,
- uint32_t *actualFrequencyHz)
- {
- TIM_TypeDef *timer;
- PLSR_TIMER_SETTING setting;
- uint32_t counterBefore;
- uint32_t counterAfter;
- uint32_t counterFinal;
- uint32_t criticalState;
- uint32_t generationBefore;
- uint32_t ownGeneration;
- uint8_t wrappedWhileUpdatesDisabled;
-
- if ((pulseOutput > 3U) || (actualFrequencyHz == NULL)
- || (PlsrTimerCalculate(pulseOutput, frequencyHz, &setting) == 0U))
- {
- return 0U;
- }
- timer = PlsrTimerMap[pulseOutput].timer;
- if ((timer->CR1 & TIM_CR1_CEN) == 0UL)
- {
- return 0U;
- }
-
- criticalState = PlsrPlatformEnterCritical();
- generationBefore = PlsrTimerQueueGeneration[pulseOutput];
- if ((timer->SR & TIM_SR_UIF) != 0UL)
- {
- PlsrHandleTimerIrq(pulseOutput);
- if (PlsrTimerQueueGeneration[pulseOutput] != generationBefore)
- {
- *actualFrequencyHz = PlsrTimerQueuedFrequencyHz[pulseOutput];
- PlsrPlatformExitCritical(criticalState);
- return 1U;
- }
- if ((timer->CR1 & TIM_CR1_CEN) == 0UL)
- {
- PlsrPlatformExitCritical(criticalState);
- return 0U;
- }
- }
-
- /* UDIS blocks shadow transfers while the three preload registers are
- replaced. The counter and PWM output continue without interruption. */
- counterBefore = timer->CNT;
- timer->CR1 |= TIM_CR1_UDIS;
- __DMB();
- if ((timer->SR & TIM_SR_UIF) != 0UL)
- {
- timer->CR1 &= ~TIM_CR1_UDIS;
- PlsrHandleTimerIrq(pulseOutput);
- if ((PlsrTimerQueueGeneration[pulseOutput] != generationBefore)
- || ((timer->CR1 & TIM_CR1_CEN) == 0UL))
- {
- uint8_t stillRunning =
- ((timer->CR1 & TIM_CR1_CEN) != 0UL) ? 1U : 0U;
-
- *actualFrequencyHz = PlsrTimerQueuedFrequencyHz[pulseOutput];
- PlsrPlatformExitCritical(criticalState);
- return stillRunning;
- }
- counterBefore = timer->CNT;
- timer->CR1 |= TIM_CR1_UDIS;
- __DMB();
- }
- PlsrTimerWriteSetting(timer, &setting);
- __DMB();
- PlsrTimerQueuedFrequencyHz[pulseOutput] = setting.actualFrequencyHz;
- PlsrTimerQueueGeneration[pulseOutput]++;
- ownGeneration = PlsrTimerQueueGeneration[pulseOutput];
- counterAfter = timer->CNT;
- timer->CR1 &= ~TIM_CR1_UDIS;
- __DMB();
- counterFinal = timer->CNT;
-
- /* With UDIS set an overflow does not set UIF. A wrapped counter proves
- that its real output edge occurred, so account for that edge once. */
- wrappedWhileUpdatesDisabled =
- ((counterAfter < counterBefore)
- || ((counterFinal < counterAfter)
- && ((timer->SR & TIM_SR_UIF) == 0UL))) ? 1U : 0U;
- if (wrappedWhileUpdatesDisabled != 0U)
- {
- PlsrPulseTimerIrq(pulseOutput);
- }
- else if ((timer->SR & TIM_SR_UIF) != 0UL)
- {
- PlsrHandleTimerIrq(pulseOutput);
- }
- *actualFrequencyHz =
- (PlsrTimerQueueGeneration[pulseOutput] == ownGeneration)
- ? setting.actualFrequencyHz
- : PlsrTimerQueuedFrequencyHz[pulseOutput];
- PlsrPlatformExitCritical(criticalState);
- return 1U;
- }
-
- void PlsrPlatformDrainPendingPulse(uint8_t pulseOutput)
- {
- if (pulseOutput <= 3U)
- {
- PlsrHandleTimerIrq(pulseOutput);
- }
- }
-
- uint32_t PlsrPlatformActiveFrequency(uint8_t pulseOutput)
- {
- return (pulseOutput <= 3U)
- ? PlsrTimerActiveFrequencyHz[pulseOutput] : 0UL;
- }
-
- void PlsrPlatformStopPulse(uint8_t pulseOutput)
- {
- if (pulseOutput <= 3U)
- {
- PlsrPulsePinCaptureIdle(pulseOutput);
- PlsrTimerStop(PlsrTimerMap[pulseOutput].timer);
- PlsrTimerActiveFrequencyHz[pulseOutput] = 0UL;
- PlsrTimerQueuedFrequencyHz[pulseOutput] = 0UL;
- PlsrTimerQueueGeneration[pulseOutput]++;
- }
- }
-
- uint8_t PlsrPlatformReadInput(uint8_t inputSelection)
- {
- if (inputSelection == 0U)
- {
- return (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5) == GPIO_PIN_SET) ? 1U : 0U;
- }
- if (inputSelection == 1U)
- {
- return (HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_12) == GPIO_PIN_SET) ? 1U : 0U;
- }
- return 0U;
- }
-
- uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload)
- {
- const PLSR_FLASH_RECORD *slotA =
- (const PLSR_FLASH_RECORD *)PLSR_FLASH_SLOT_A_ADDRESS;
- const PLSR_FLASH_RECORD *slotB =
- (const PLSR_FLASH_RECORD *)PLSR_FLASH_SLOT_B_ADDRESS;
- const PLSR_FLASH_RECORD *selected = NULL;
- const PLSR_BACKUP_CONFIG_RECORD *backupConfig =
- (const PLSR_BACKUP_CONFIG_RECORD *)PLSR_BACKUP_CONFIG_ADDRESS;
- const PLSR_BACKUP_POSITION_RECORD *backupPosition;
- uint8_t validA;
- uint8_t validB;
- uint8_t haveConfig = 0U;
-
- if (payload == NULL)
- {
- return 0U;
- }
-
- validA = PlsrFlashRecordIsValid(slotA);
- validB = PlsrFlashRecordIsValid(slotB);
- if ((validA != 0U) && (validB != 0U))
- {
- selected = (PlsrGenerationIsNewer(slotB->generation,
- slotA->generation) != 0U)
- ? slotB : slotA;
- }
- else if (validA != 0U)
- {
- selected = slotA;
- }
- else if (validB != 0U)
- {
- selected = slotB;
- }
-
- if (selected != NULL)
- {
- *payload = selected->payload;
- haveConfig = 1U;
- }
- else
- {
- (void)memset(payload, 0, sizeof(*payload));
- }
-
- if (PlsrBackupConfigIsValid(backupConfig) != 0U)
- {
- payload->config = backupConfig->config;
- haveConfig = 1U;
- }
- backupPosition = PlsrNewestBackupPosition();
- if (backupPosition != NULL)
- {
- payload->position = backupPosition->position;
- payload->positionValid = backupPosition->positionValid;
- payload->wasBusy = backupPosition->wasBusy;
- }
- return haveConfig;
- }
-
- uint8_t PlsrPlatformSave(const PLSR_PERSIST_PAYLOAD *payload)
- {
- const PLSR_FLASH_RECORD *slotA =
- (const PLSR_FLASH_RECORD *)PLSR_FLASH_SLOT_A_ADDRESS;
- const PLSR_FLASH_RECORD *slotB =
- (const PLSR_FLASH_RECORD *)PLSR_FLASH_SLOT_B_ADDRESS;
- uint8_t validA;
- uint8_t validB;
- uint32_t newestGeneration = 0UL;
- uint32_t targetAddress;
- uint32_t targetSector;
- uint32_t sectorError;
- uint32_t index;
- uint32_t wordCount;
- const uint32_t *words;
- FLASH_EraseInitTypeDef erase;
- HAL_StatusTypeDef status = HAL_OK;
-
- if (payload == NULL)
- {
- return 0U;
- }
-
- validA = PlsrFlashRecordIsValid(slotA);
- validB = PlsrFlashRecordIsValid(slotB);
- if ((validA != 0U) && (validB != 0U))
- {
- if (PlsrGenerationIsNewer(slotB->generation, slotA->generation) != 0U)
- {
- newestGeneration = slotB->generation;
- targetAddress = PLSR_FLASH_SLOT_A_ADDRESS;
- targetSector = FLASH_SECTOR_10;
- }
- else
- {
- newestGeneration = slotA->generation;
- targetAddress = PLSR_FLASH_SLOT_B_ADDRESS;
- targetSector = FLASH_SECTOR_11;
- }
- }
- else if (validA != 0U)
- {
- newestGeneration = slotA->generation;
- targetAddress = PLSR_FLASH_SLOT_B_ADDRESS;
- targetSector = FLASH_SECTOR_11;
- }
- else if (validB != 0U)
- {
- newestGeneration = slotB->generation;
- targetAddress = PLSR_FLASH_SLOT_A_ADDRESS;
- targetSector = FLASH_SECTOR_10;
- }
- else
- {
- targetAddress = PLSR_FLASH_SLOT_A_ADDRESS;
- targetSector = FLASH_SECTOR_10;
- }
-
- (void)memset(&PlsrFlashRecordBuffer, 0, sizeof(PlsrFlashRecordBuffer));
- PlsrFlashRecordBuffer.magic = PLSR_FLASH_MAGIC;
- PlsrFlashRecordBuffer.version = PLSR_FLASH_VERSION;
- PlsrFlashRecordBuffer.payloadSize = sizeof(PLSR_PERSIST_PAYLOAD);
- PlsrFlashRecordBuffer.generation = newestGeneration + 1UL;
- PlsrFlashRecordBuffer.payload = *payload;
- PlsrFlashRecordBuffer.crc32 = PlsrFlashRecordCrc(&PlsrFlashRecordBuffer);
-
- if (HAL_FLASH_Unlock() != HAL_OK)
- {
- return 0U;
- }
- __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR
- | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR
- | FLASH_FLAG_PGSERR);
- erase.TypeErase = FLASH_TYPEERASE_SECTORS;
- erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
- erase.Sector = targetSector;
- erase.NbSectors = 1U;
- if (HAL_FLASHEx_Erase(&erase, §orError) != HAL_OK)
- {
- status = HAL_ERROR;
- }
-
- words = (const uint32_t *)&PlsrFlashRecordBuffer;
- wordCount = sizeof(PlsrFlashRecordBuffer) / sizeof(uint32_t);
- if (status == HAL_OK)
- {
- for (index = 1UL; index < wordCount; index++)
- {
- if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,
- targetAddress + index * 4UL,
- words[index]) != HAL_OK)
- {
- status = HAL_ERROR;
- break;
- }
- }
- }
- if ((status == HAL_OK)
- && (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, targetAddress,
- PLSR_FLASH_MAGIC) != HAL_OK))
- {
- status = HAL_ERROR;
- }
- if (HAL_FLASH_Lock() != HAL_OK)
- {
- status = HAL_ERROR;
- }
-
- if ((status == HAL_OK)
- && (PlsrFlashRecordIsValid(
- (const PLSR_FLASH_RECORD *)targetAddress) != 0U))
- {
- return 1U;
- }
- return 0U;
- }
-
- void PlsrPlatformCheckpointConfig(const PLSR_CONFIG *config)
- {
- PLSR_BACKUP_CONFIG_RECORD *record =
- (PLSR_BACKUP_CONFIG_RECORD *)PLSR_BACKUP_CONFIG_ADDRESS;
-
- if (config == NULL)
- {
- return;
- }
- record->magic = 0UL;
- record->config = *config;
- record->crc32 = PlsrCrc32(&record->config, sizeof(record->config));
- __DMB();
- record->magic = PLSR_BACKUP_CONFIG_MAGIC;
- __DMB();
- }
-
- void PlsrPlatformCheckpointPosition(int32_t position,
- uint8_t positionValid,
- uint8_t wasBusy)
- {
- PLSR_BACKUP_POSITION_RECORD *slots =
- (PLSR_BACKUP_POSITION_RECORD *)PLSR_BACKUP_POSITION_ADDRESS;
- PLSR_BACKUP_POSITION_RECORD *record;
-
- PlsrBackupPositionGeneration++;
- record = &slots[PlsrBackupPositionGeneration & 1UL];
- record->magic = 0UL;
- record->generation = PlsrBackupPositionGeneration;
- record->position = position;
- record->positionValid = (positionValid != 0U) ? 1U : 0U;
- record->wasBusy = (wasBusy != 0U) ? 1U : 0U;
- record->reserved = 0U;
- record->crc32 = PlsrCrc32(&record->generation,
- sizeof(record->generation)
- + sizeof(record->position)
- + sizeof(record->positionValid)
- + sizeof(record->wasBusy)
- + sizeof(record->reserved));
- __DMB();
- record->magic = PLSR_BACKUP_POSITION_MAGIC;
- __DMB();
- }
-
- uint32_t PlsrPlatformEnterCritical(void)
- {
- uint32_t state = __get_PRIMASK();
- __disable_irq();
- __DMB();
- return state;
- }
-
- void PlsrPlatformExitCritical(uint32_t state)
- {
- __DMB();
- if (state == 0UL)
- {
- __enable_irq();
- }
- }
-
- static void PlsrHandleTimerIrq(uint8_t pulseOutput)
- {
- TIM_TypeDef *timer = PlsrTimerMap[pulseOutput].timer;
- #if PLSR_ENABLE_IRQ_CYCLE_DIAG
- uint32_t startedAt;
- uint32_t elapsedCycles;
- #endif
-
- if (((timer->SR & TIM_SR_UIF) != 0UL)
- && ((timer->DIER & TIM_DIER_UIE) != 0UL))
- {
- #if PLSR_ENABLE_IRQ_CYCLE_DIAG
- startedAt = DWT->CYCCNT;
- #endif
- timer->SR = ~TIM_SR_UIF;
- PlsrTimerActiveFrequencyHz[pulseOutput] =
- PlsrTimerQueuedFrequencyHz[pulseOutput];
- PlsrPulseTimerIrq(pulseOutput);
- #if PLSR_ENABLE_IRQ_CYCLE_DIAG
- elapsedCycles = DWT->CYCCNT - startedAt;
- PlsrIrqCount[pulseOutput]++;
- PlsrIrqLastCycles[pulseOutput] = elapsedCycles;
- if (elapsedCycles > PlsrIrqMaxCycles[pulseOutput])
- {
- PlsrIrqMaxCycles[pulseOutput] = elapsedCycles;
- }
- #endif
- }
- }
-
- void TIM1_UP_TIM10_IRQHandler(void)
- {
- PlsrHandleTimerIrq(0U);
- }
-
- void TIM8_UP_TIM13_IRQHandler(void)
- {
- PlsrHandleTimerIrq(1U);
- }
-
- void TIM1_TRG_COM_TIM11_IRQHandler(void)
- {
- PlsrHandleTimerIrq(2U);
- }
-
- void TIM8_TRG_COM_TIM14_IRQHandler(void)
- {
- PlsrHandleTimerIrq(3U);
- }
-
- #endif /* PLSR_HOST_TEST */
|