因为GPIO中断会引起异常,暂时用软件方式判断先跳过去。结果定时器中断也异常,一步一步地填坑。
我的代码:
[C] 纯文本查看 复制代码 /*
*********************************************************************************************************
* 函 数 名: TrigCallback
* 功能说明: 启动硬件触发,并设置触发电平
* 形 参: _TrigVolt 触发电压,单位V
* 返 回 值: 无
*********************************************************************************************************
*/
void TrigCallback(uint gpio, uint32_t events)
{
if (gpio_get(25) == 0)
{
gpio_put(25, 1); /* 点亮LED */
}
else
{
gpio_put(25, 0); /* 熄灭LED */
}
/* 停止GPIO中断 */
// gpio_set_irq_enabled(PIN_TRIG, GPIO_IRQ_EDGE_RISE, false);
// 立即读取触发位置
dma_channel_hw_t *hw = dma_channel_hw_addr(g_tDSO.data_chan);
g_tDSO.TrigPosDma = hw->write_addr;
g_tDSO.Trigged = 2;
//
/* 计算触发结束时刻 */
int64_t t0;
t0 = 50000; //
add_alarm_in_ms(t0, TrigAlarmCallbak, 0, true);
}
alarm_callback_t TrigAlarmCallbak(alarm_id_t id, void *user_data)
{
if (gpio_get(25) == 0)
{
gpio_put(25, 1); /* 点亮LED */
}
else
{
gpio_put(25, 0); /* 熄灭LED */
}
//dma_channel_abort(g_tDSO.ctrl_chan);
//dma_channel_abort(g_tDSO.data_chan);
dma_hw->abort = (1u << g_tDSO.ctrl_chan) | (1u << g_tDSO.data_chan);
while (dma_hw->abort & ((1ul << g_tDSO.ctrl_chan) | (1u << g_tDSO.data_chan))) ;
bsp_StopDso();
}
开启定时器时产生异常,异常位置:
[C] 纯文本查看 复制代码 /*! \brief Acquire a spin lock without disabling interrupts (hence unsafe)
* \ingroup hardware_sync
*
* \param lock Spinlock instance
*/
__force_inline static void spin_lock_unsafe_blocking(spin_lock_t *lock) {
// Note we don't do a wfe or anything, because by convention these spin_locks are VERY SHORT LIVED and NEVER BLOCK and run
// with INTERRUPTS disabled (to ensure that)... therefore nothing on our core could be blocking us, so we just need to wait on another core
// anyway which should be finished soon
while (__builtin_expect(!*lock, 0));
__mem_fence_acquire();
}
解释
1.引言在很多源码如Linux内核、Glib等,我们都能看到likely()和unlikely()这两个宏,通常这两个宏定义是下面这样的形式。 #define likely(x) __builtin_expect(!!(x), 1)#define unlikely(x) __builtin_expect(!!(x), 0)
可以看出这2个宏都是使用函数 __builtin_expect()实现的, __builtin_expect()函数是GCC的一个内建函数(build-in function).
2. 函数声明函数__builtin_expect()是GCC v2.96版本引入的, 其声明如下:long __builtin_expect(long exp, long c);
2.1. 功能描述由于大部分程序员在分支预测方面做得很糟糕,所以GCC 提供了这个内建函数来帮助程序员处理分支预测. 你期望 exp 表达式的值等于常量 c, 看 c 的值, 如果 c 的值为0(即期望的函数返回值), 那么 执行 if 分支的的可能性小, 否则执行 else 分支的可能性小(函数的返回值等于第一个参数 exp). GCC在编译过程中,会将可能性更大的代码紧跟着前面的代码,从而减少指令跳转带来的性能上的下降, 达到优化程序的目的. 通常,你也许会更喜欢使用 gcc 的一个参数 '-fprofile-arcs' 来收集程序运行的关于执行流程和分支走向的实际反馈信息,但是对于很多程序来说,数据是很难收集的。 2.2. 参数详解 ① exp exp 为一个整型表达式, 例如: (ptr != NULL) ② c c 必须是一个编译期常量, 不能使用变量 2.3. 返回值 返回值等于 第一个参数 exp
|