Skip to content

常见问题 失去响应

liuzikai edited this page Jan 17, 2022 · 1 revision

对于控制代码而言,稳定性是第一重要的,如果控制程序在赛场上崩溃,直接就是非战斗减员!

程序崩溃的情况有很多种,从最基本的:除以 0,dereference null,到高层次的违反 ChibiOS API class 等。

程序崩溃的表现一般是先失控然后失去响应,这是因为电调在没有控制信号时会沿用上次的控制信号一段时间。

对于 ChibiOS 能捕获到的崩溃(halt),开发板的表现是红灯亮、绿灯(指红灯旁边的灯)灭,其余绿色 LED 静止,可能有蜂鸣器长鸣。这一部分代码在 led.cpp 中定义(附于文末)。

遇到崩溃时,优先考虑以下可能性:

  • 调用了错误 Class 的 ChibiOS API(详见 ChibiOS 关键区与锁
  • 线程栈溢出(详见 ChibiOS 线程编写
  • 除以 0 或 dereference null
  • 线程死循环缺少 sleep (一般表现是无响应,或异常延迟,如果 Shell 还能使用,输入 stats 指令,可以看到此线程占用率接近 100%,参考 ChibiOS 性能与资源占用)

附录:ChibiOS halt 处理代码,该函数在 chconf.hCH_CFG_SYSTEM_HALT_HOOK(reason) 调用。

extern "C" {
/**
 * @note This function maybe called in very complicated situations, such as system locked states. Be sure to prepare for
 *       them, instead of inducing more complicated error.
 */
void set_led_when_halt(void) {

    /// Turn on red LED when halt
    LED_PAD_ON(GPIOF, GPIOE_LED_RED);    // LED_RED_ON
    LED_PAD_OFF(GPIOF, GPIOF_LED_GREEN); // LED_GREEN_OFF



    // Now system is unlocked

    PWMConfig pwm_config = {
            1000000,
            1000000, // Default playing_note: 1Hz
            nullptr,
            {
                    {PWM_OUTPUT_ACTIVE_HIGH, nullptr},  // it's all CH1 for current support boards
                    {PWM_OUTPUT_DISABLED, nullptr},
                    {PWM_OUTPUT_DISABLED, nullptr},
                    {PWM_OUTPUT_DISABLED, nullptr}
            },
            0,
            0
    };

    if ((BUZZER_PWM_DRIVER.state != PWM_STOP) && (BUZZER_PWM_DRIVER.state != PWM_READY)) {

        // Unlock system if in system locked state
        // The following code is extract from chSysUnconditionalUnlock() with debug check eliminated
        if (!port_irq_enabled(port_get_irq_status())) {  // is in locked state
            _stats_stop_measure_crit_thd();
            port_unlock();
        }
        // Hopefully no content switch will happen here...

        pwmStart(&BUZZER_PWM_DRIVER, &pwm_config);  // require unlock state

        chSysUnconditionalLock();  // recover

    }  // if PWM has already started, do nothing

    pwmChangePeriod(&BUZZER_PWM_DRIVER, 1000000 / 349);
    pwmEnableChannel(&BUZZER_PWM_DRIVER, 0, PWM_PERCENTAGE_TO_WIDTH(&BUZZER_PWM_DRIVER, 5000)); // 50%

    chSysUnconditionalLock();  // lock in following infinity loop in chSysHalt()
}
}
Clone this wiki locally