#include "sync_pulse.h" #include "timeouts.h" #include "id.h" extern TIM_HandleTypeDef htim8; volatile int watchdog_active = 0; volatile int watchdog_started = 0; volatile int request_syncout_activation = 0; typedef enum { SYNC_PULSE_MODE_WATCHDOG = 0, SYNC_PULSE_MODE_SYNCOUT = 1, } SyncPulseMode_t; static volatile SyncPulseMode_t s_mode = SYNC_PULSE_MODE_WATCHDOG; void SYNC_Pulse_RequestSyncout(uint8_t enable) { request_syncout_activation = enable ? 1 : 0; } static void SYNC_Pulse_SwitchToSyncout(void) { /* Stop timer + interrupts, remap pin to GPIO output */ SYNC_PULSE_TIM_STOP(); SYNC_Pulse_EnableGPIO(); /* Optional: reset flags/state for syncout mode */ watchdog_active = 0; s_mode = SYNC_PULSE_MODE_SYNCOUT; } static void SYNC_Pulse_SwitchToWatchdog(void) { /* Remap pin back to TIM8_CH1 AF, start PWM interrupts */ SYNC_Pulse_EnableTIM8(); SYNC_PULSE_TIM_START(); /* Optional: reset flags/state for watchdog mode */ watchdog_active = 0; s_mode = SYNC_PULSE_MODE_WATCHDOG; } /* Call this from main loop / fast task */ void SYNC_Pulse_Poll(void) { uint8_t req = (request_syncout_activation != 0); if (req && (s_mode != SYNC_PULSE_MODE_SYNCOUT)) { __disable_irq(); SYNC_Pulse_SwitchToSyncout(); __enable_irq(); } else if (!req && (s_mode != SYNC_PULSE_MODE_WATCHDOG)) { __disable_irq(); SYNC_Pulse_SwitchToWatchdog(); __enable_irq(); } } uint8_t SYNC_Pulse_IsSyncoutMode(void) { return (s_mode == SYNC_PULSE_MODE_SYNCOUT); } /* ========================================================= Optional user hook: called from HAL callback (keep it simple: set this from your app code if you want) ========================================================= */ static void (*s_sync_pulse_cb)(void) = 0; void SYNC_Pulse_SetCallback(void (*cb)(void)) { s_sync_pulse_cb = cb; } /* ========================================================= IRQ enable/disable ========================================================= */ static void SYNC_Pulse_TIM8_EnableNVIC(void) { /* TIM8 has two common IRQ lines on STM32G4: - TIM8_CC_IRQn : capture/compare interrupts (PWM CC) - TIM8_UP_TIM13_IRQn : update interrupt (period elapsed) */ HAL_NVIC_SetPriority(TIM8_CC_IRQn, 5, 0); HAL_NVIC_EnableIRQ(TIM8_CC_IRQn); HAL_NVIC_SetPriority(TIM8_UP_IRQn, 5, 0); HAL_NVIC_EnableIRQ(TIM8_UP_IRQn); } static void SYNC_Pulse_TIM8_DisableNVIC(void) { HAL_NVIC_DisableIRQ(TIM8_CC_IRQn); HAL_NVIC_DisableIRQ(TIM8_UP_IRQn); } /* ========================================================= Public API ========================================================= */ /** * @brief Configure PA15 as TIM8_CH1 PWM output (AF2). * NOTE: This only sets the pin muxing. Timer configuration is assumed done elsewhere. */ void SYNC_Pulse_EnableTIM8(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Remove previous GPIO config on PA15 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_15); /* Configure PA15 alternate function = TIM8_CH1 (AF2) */ __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF2_TIM8; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* Enable TIM8 interrupts in NVIC */ SYNC_Pulse_TIM8_EnableNVIC(); } /** * @brief Start TIM8 PWM on CH1 with interrupt enabled. * * This enables CC interrupts for the channel and will call: * HAL_TIM_PWM_PulseFinishedCallback() * (and/or other HAL callbacks depending on HAL internals) */ void SYNC_PULSE_TIM_START(void) { /* Start PWM + interrupt */ HAL_TIM_PWM_Start_IT(&htim8, TIM_CHANNEL_1); /* If you also want update (period elapsed) interrupts, uncomment: HAL_TIM_Base_Start_IT(&htim8); */ } void SYNC_PULSE_TIM_STOP(void) { /* Start PWM + interrupt */ HAL_TIM_PWM_Stop_IT(&htim8, TIM_CHANNEL_1); /* If you also want update (period elapsed) interrupts, uncomment: HAL_TIM_Base_Start_IT(&htim8); */ } /** * @brief Disable TIM8_CH1 PWM and return PA15 to GPIO output mode. */ void SYNC_Pulse_EnableGPIO(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Stop PWM output on TIM8 CH1 (IT-safe stop) */ HAL_TIM_PWM_Stop_IT(&htim8, TIM_CHANNEL_1); /* If you started base update IT, stop it too: HAL_TIM_Base_Stop_IT(&htim8); */ /* Disable NVIC lines */ SYNC_Pulse_TIM8_DisableNVIC(); /* Remove AF mapping */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_15); /* Reconfigure PA15 as standard push-pull output */ __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* Optional: set known state */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); } void SYNC_Pulse_GPIO_set(uint8_t state) { HAL_GPIO_WritePin(SYNC_OUT_GPIO_Port, SYNC_OUT_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); } /* ========================================================= Actual IRQ handlers (DEFINED HERE, not in stm32xx_it.c) ========================================================= */ void TIM8_CC_IRQHandler(void) { HAL_TIM_IRQHandler(&htim8); } void TIM8_UP_TIM13_IRQHandler(void) { HAL_TIM_IRQHandler(&htim8); } /* ========================================================= HAL callbacks (choose whichever you want) ========================================================= */ /* Called for Update event if Base_Start_IT (or update IT) is enabled */ /*void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM8) { // Period elapsed (update) if (s_sync_pulse_cb) s_sync_pulse_cb(); } }*/ #include "can_port.h" /* Often triggered when PWM channel finishes a pulse when using PWM_Start_IT */ #if defined(T06301) void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM8) { if (!watchdog_active){ watchdog_active = 1; // ✅ Pulse finished watchdog_started = 1; can_port_send_msg_def(&MSG_ID_EMPF4); Timeout_StartIfStopped(20, TIM16->CNT); // deberia mejorarlo bastante esto, en vez de FIEONA_advance(); } /* PWM CC event */ if (s_sync_pulse_cb) s_sync_pulse_cb(); } } #elif defined(cfgejemplo) #endif