2026-06-26 00:57:59 +08:00
|
|
|
/**
|
|
|
|
|
* @file ethercat_sync.cpp
|
|
|
|
|
* @brief EtherCAT SYNC0 周期同步实现。
|
|
|
|
|
*/
|
|
|
|
|
#include "comm/ethercat_sync.h"
|
|
|
|
|
#include "comm/ethercat_slave.h"
|
|
|
|
|
#include "sys/config.h"
|
|
|
|
|
#include "sys/task_manager.h"
|
|
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
#include "gd32e50x_rcu.h"
|
|
|
|
|
#include "gd32e50x_gpio.h"
|
|
|
|
|
#include "gd32e50x_exti.h"
|
|
|
|
|
#include "gd32e50x_misc.h"
|
|
|
|
|
#if (CONFIG_ETHERCAT_SYNC_MODE == 1)
|
|
|
|
|
#include "gd32e50x_timer.h"
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EthercatSync::init()
|
|
|
|
|
{
|
|
|
|
|
/* 使能 GPIOB 时钟(SYNC0=PB0 / IRQ=PB1 / SYNC1=PB2) */
|
|
|
|
|
rcu_periph_clock_enable(RCU_GPIOB);
|
|
|
|
|
rcu_periph_clock_enable(RCU_AF);
|
|
|
|
|
|
|
|
|
|
/* 配置三个引脚为上拉输入(EXTI 下降沿触发:LAN9252 输出低有效脉冲) */
|
|
|
|
|
gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ,
|
|
|
|
|
CONFIG_ESC_SYNC0_PIN | CONFIG_ESC_IRQ_PIN | CONFIG_ESC_SYNC1_PIN);
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_ETHERCAT_SYNC_MODE == 0)
|
|
|
|
|
/* ---- 默认:EXTI 外部触发模式 ---- */
|
|
|
|
|
/* SYNC0:PB0 -> EXTI0,下降沿,preempt=0 */
|
|
|
|
|
gpio_exti_source_select(CONFIG_ESC_SYNC0_EXTI_SOURCE_PORT, CONFIG_ESC_SYNC0_EXTI_SOURCE_PIN);
|
|
|
|
|
exti_init(CONFIG_ESC_SYNC0_EXTI, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
|
|
|
|
|
exti_interrupt_enable(CONFIG_ESC_SYNC0_EXTI);
|
|
|
|
|
exti_interrupt_flag_clear(CONFIG_ESC_SYNC0_EXTI);
|
|
|
|
|
nvic_irq_enable(CONFIG_ESC_SYNC0_IRQn, CONFIG_IRQ_PREEMPT_ETHERCAT_SYNC, 0U);
|
|
|
|
|
|
|
|
|
|
/* ESC IRQ:PB1 -> EXTI1,下降沿,preempt=1 */
|
|
|
|
|
gpio_exti_source_select(CONFIG_ESC_IRQ_EXTI_SOURCE_PORT, CONFIG_ESC_IRQ_EXTI_SOURCE_PIN);
|
|
|
|
|
exti_init(CONFIG_ESC_IRQ_EXTI, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
|
|
|
|
|
exti_interrupt_enable(CONFIG_ESC_IRQ_EXTI);
|
|
|
|
|
exti_interrupt_flag_clear(CONFIG_ESC_IRQ_EXTI);
|
|
|
|
|
nvic_irq_enable(CONFIG_ESC_IRQ_IRQn, CONFIG_IRQ_PREEMPT_ETHERCAT_ESC, 0U);
|
|
|
|
|
|
|
|
|
|
/* SYNC1:PB2 -> EXTI2,下降沿,preempt=1(备用) */
|
|
|
|
|
gpio_exti_source_select(CONFIG_ESC_SYNC1_EXTI_SOURCE_PORT, CONFIG_ESC_SYNC1_EXTI_SOURCE_PIN);
|
|
|
|
|
exti_init(CONFIG_ESC_SYNC1_EXTI, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
|
|
|
|
|
exti_interrupt_enable(CONFIG_ESC_SYNC1_EXTI);
|
|
|
|
|
exti_interrupt_flag_clear(CONFIG_ESC_SYNC1_EXTI);
|
|
|
|
|
nvic_irq_enable(CONFIG_ESC_SYNC1_IRQn, CONFIG_IRQ_PREEMPT_ETHERCAT_SYNC1, 0U);
|
|
|
|
|
#else
|
|
|
|
|
/* ---- 降级模式:TIMER0 内部定时 ---- */
|
|
|
|
|
rcu_periph_clock_enable(RCU_TIMER0);
|
|
|
|
|
timer_parameter_struct timer_initpara;
|
|
|
|
|
timer_struct_para_init(&timer_initpara);
|
|
|
|
|
/* 100us 周期:180MHz / (179+1) / (99+1) = 10kHz = 100us */
|
|
|
|
|
timer_initpara.prescaler = 179U;
|
|
|
|
|
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
|
|
|
|
|
timer_initpara.counterdirection = TIMER_COUNTER_UP;
|
|
|
|
|
timer_initpara.period = 99U;
|
|
|
|
|
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
|
|
|
|
|
timer_init(TIMER0, &timer_initpara);
|
|
|
|
|
timer_interrupt_flag_clear(TIMER0, TIMER_INT_FLAG_UP);
|
|
|
|
|
timer_interrupt_enable(TIMER0, TIMER_INT_UP);
|
|
|
|
|
nvic_irq_enable(TIMER0_IRQn, CONFIG_IRQ_PREEMPT_ETHERCAT_SYNC, 0U);
|
|
|
|
|
timer_enable(TIMER0);
|
2026-06-29 01:51:02 +08:00
|
|
|
|
|
|
|
|
/* ESC IRQ:PB1 -> EXTI1,下降沿,preempt=1 */
|
|
|
|
|
gpio_exti_source_select(CONFIG_ESC_IRQ_EXTI_SOURCE_PORT, CONFIG_ESC_IRQ_EXTI_SOURCE_PIN);
|
|
|
|
|
exti_init(CONFIG_ESC_IRQ_EXTI, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
|
|
|
|
|
exti_interrupt_enable(CONFIG_ESC_IRQ_EXTI);
|
|
|
|
|
exti_interrupt_flag_clear(CONFIG_ESC_IRQ_EXTI);
|
|
|
|
|
nvic_irq_enable(CONFIG_ESC_IRQ_IRQn, CONFIG_IRQ_PREEMPT_ETHERCAT_ESC, 0U);
|
|
|
|
|
|
|
|
|
|
/* SYNC1:PB2 -> EXTI2,下降沿,preempt=1(备用) */
|
|
|
|
|
gpio_exti_source_select(CONFIG_ESC_SYNC1_EXTI_SOURCE_PORT, CONFIG_ESC_SYNC1_EXTI_SOURCE_PIN);
|
|
|
|
|
exti_init(CONFIG_ESC_SYNC1_EXTI, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
|
|
|
|
|
exti_interrupt_enable(CONFIG_ESC_SYNC1_EXTI);
|
|
|
|
|
exti_interrupt_flag_clear(CONFIG_ESC_SYNC1_EXTI);
|
|
|
|
|
nvic_irq_enable(CONFIG_ESC_SYNC1_IRQn, CONFIG_IRQ_PREEMPT_ETHERCAT_SYNC1, 0U);
|
2026-06-26 00:57:59 +08:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 01:51:02 +08:00
|
|
|
__attribute__((section(".ramfunc"), noinline))
|
2026-06-26 00:57:59 +08:00
|
|
|
void EthercatSync::onSync0Exti()
|
|
|
|
|
{
|
2026-06-29 01:51:02 +08:00
|
|
|
/* 直接寄存器访问,绕过 GD32 库函数以消除可变抖动 */
|
|
|
|
|
if ((EXTI_PD & (uint32_t)CONFIG_ESC_SYNC0_EXTI) != RESET) {
|
|
|
|
|
EXTI_PD = (uint32_t)CONFIG_ESC_SYNC0_EXTI;
|
2026-06-26 00:57:59 +08:00
|
|
|
EthercatSlave::periodicIsr();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EthercatSync::onEscIrqExti()
|
|
|
|
|
{
|
|
|
|
|
if (exti_interrupt_flag_get(CONFIG_ESC_IRQ_EXTI) != RESET) {
|
|
|
|
|
exti_interrupt_flag_clear(CONFIG_ESC_IRQ_EXTI);
|
|
|
|
|
/* 极简:仅置位任务,事件处理移主循环 */
|
|
|
|
|
TaskManager::set(1UL << TASK_ETHERCAT_PROCESS);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EthercatSync::onSync1Exti()
|
|
|
|
|
{
|
|
|
|
|
if (exti_interrupt_flag_get(CONFIG_ESC_SYNC1_EXTI) != RESET) {
|
|
|
|
|
exti_interrupt_flag_clear(CONFIG_ESC_SYNC1_EXTI);
|
|
|
|
|
/* SYNC1 备用,暂不处理 */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EthercatSync::onTimerIrq()
|
|
|
|
|
{
|
|
|
|
|
#if (CONFIG_ETHERCAT_SYNC_MODE == 1)
|
|
|
|
|
if (timer_interrupt_flag_get(TIMER0, TIMER_INT_FLAG_UP) != RESET) {
|
|
|
|
|
timer_interrupt_flag_clear(TIMER0, TIMER_INT_FLAG_UP);
|
|
|
|
|
EthercatSlave::periodicIsr();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---- 中断入口 C 包装 ---- */
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_ETHERCAT_SYNC_MODE == 0)
|
2026-06-29 01:51:02 +08:00
|
|
|
__attribute__((section(".ramfunc"), noinline))
|
2026-06-26 00:57:59 +08:00
|
|
|
void EXTI0_IRQHandler(void) { EthercatSync::onSync0Exti(); }
|
|
|
|
|
void EXTI1_IRQHandler(void) { EthercatSync::onEscIrqExti(); }
|
|
|
|
|
void EXTI2_IRQHandler(void) { EthercatSync::onSync1Exti(); }
|
|
|
|
|
#else
|
|
|
|
|
void TIMER0_IRQHandler(void) { EthercatSync::onTimerIrq(); }
|
2026-06-29 01:51:02 +08:00
|
|
|
void EXTI1_IRQHandler(void) { EthercatSync::onEscIrqExti(); }
|
|
|
|
|
void EXTI2_IRQHandler(void) { EthercatSync::onSync1Exti(); }
|
2026-06-26 00:57:59 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
} /* extern "C" */
|