工具/软件:
尊敬的 TI 支持团队:
我们正在使用 TI-RTOS 开发 CC2651R3SIPA 固件、目前正在实现一个 ADC 中断处理程序(adc_complete_isr
)、该中断处理程序从 FIFO 中读取数据并执行一些处理。
就是这个中断 不由操作系统内核管理 —我们将其配置为 零延迟中断 直接修改 NVIC 矢量表而不使用IntRegister()
,以避免干扰 TI-RTOS 管理的中断。
在 ISR 中、我们AUX_ADC_IRQ
AUX_ADC_DONE
使用以下行清除 ADC 中断标志(和):
HWREG(AUX_EVCTL_BASE + AUX_EVCTL_O_EVTOMCUFLAGSCLR) |=
(AUX_EVCTL_EVTOMCUFLAGSCLR_AUX_ADC_IRQ | AUX_EVCTL_EVTOMCUFLAGSCLR_AUX_ADC_DONE );
HwiP_clearInterrupt(INT_AUX_ADC_IRQ);
我们最初放置了这个标志清除逻辑 发展 ISR 的组成部分。 但是、这样做时、系统会持续重新进入 ISR、就好像中断标志从未被清除过一样。
移动标志清除逻辑 到达 ISR 的末尾 、该行为将按预期实现、并且每次转换仅触发一次中断。
我们希望了解:
-
为什么在 ISR 开始时清除中断标志会使其连续重新进入?
-
为什么将标志清除移至结尾会解决问题?
-
在结尾而不是开头清除旗帜是否有任何副作用?
如果您能提供任何技术见解或文档参考、我们将不胜感激。
此外、我们还将附加adc_open
和adc_complete_isr
实现设置和 ISR 处理的函数的源代码。
void ADC_OPEN (void)
{
//防止转换到待机状态
Power_setConstraint (PowerCC26XX_SB_disallow);
AUXADCDisable ();
//启用 ADC 并设置触发器
AUXADCEnableSync (ADCCC26XX_VDDS_REFERENCE、ADCCC26XX_SAMPLING_DURATION_2P7_US、ADCCC26XX_TRIGGER_MANUAL);
//获得用于 ADC 转换校正的增益和偏移量
S_adcCtx.adcGain = AUXADCGetAdjustmentGain (AUXADC_REF_VDDS_REL);
S_adcCtx.adcOffset = NOROM_AUXADCGetAdjustmentOffset (AUXADC_REF_VDDS_REL);
//清除中断标志
HWREG (AUX_EVCTL_BASE + AUX_EVCTL_O_EVTOMCUFLAGSCLR)|=(AUX_EVCTL_EVTOMCUFLAGSCLR_AUX_ADC_IRQ | AUX_EVCTL_EVTOMCUFLAGSCLR_AUX_ADC_DONE);
HwiP_clearInterrupt (INT_AUX_ADC_IRQ);
// IntRegister()可用于注册 ISR、但使用它会干扰操作系统管理的中断。
//因此、我们避免使用它、而是直接将入口指针添加到向量表中。
uint32_t ui32value;
ui32value = HWREG (NVIC_vtable);
HWREG (ui32value +(INT_AUX_ADC_IRQ * 4))=(uint32_t) ADC_FULL_ISR;//将矢量数乘以地址大小(4字节)以移动指针
//启用中断
IntPrioritySet (INT_AUX_ADC_IRQ、INT_PRI_LEVEL0);
IntEnable (INT_AUX_ADC_IRQ);
}
void ADC_COMPLET_ISR (void)
{
//从 FIFO 检索数据
S_adcMem[s_adcCtx.convertIndex]= HWREG (AUX_ANAIF_BASE + AUX_ANAIF_O_ADCFIFO);
S_adcCtx.singleChannelFlag = true;
//对 ADC 输入值执行校正、因为它们是按比例缩放的。
//驱动程序提供了一个用于更正的 API、但为了最大限度地减少开销、我们直接执行计算。
S_adcMem[s_adcCtx.convertIndex]=(int16_t)(((( int32_t) s_adcMem[s_adcCtx.convertIndex]+ s_adcCtx.adcOffset)* s_adcCtx.adcGain)+ 16384)/ 32768);
if (s_adcMem[s_adcCtx.convertIndex]< 0){
S_adcMem[s_adcCtx.convertIndex]= 0;
}如果(s_adcMem[s_adcCtx.convertIndex]> 4095){、则为"其他"
S_adcMem[s_adcCtx.convertIndex]= 4095;
}
if (s_adcCtx.state == ADC_STATE_QUADE_CHANNEL_STAGE_2 && s_adcCtx.convertIndex == 4){
// index4的 ADC 转换完成中断(电池电压)。
//由于不需要连续转换、因此将 convertIndex 初始化为0以防止进一步转换。
S_adcCtx.convertIndex = 0;
}其他{
s_adcCtx.convertIndex =(s_adcCtx.convertIndex + 1)% s_adcCtx.convertCount;
}
if (s_adcCtx.state!= ADC_STATE_SINGLE_CHANNEL && s_adcCtx.convertIndex == 0){
//一旦完成一个完整的转换周期
S_adcCtx.stateSwitchPeriod++;
const ADC_CONV_TABLE_t* adcTable =&s_adcStateTable[(s_adcCtx.state - 1)& 0x03];
if(s_adcCtx.stateSwitchPeriod >= adcTable->maxPeriod){
s_adcCtx.state = adcTable->nextConvertState;
s_adcCtx.convertCount = adcTable->convertCount;
S_adcCtx.stateSwitchPeriod = 0;
}
}
if (s_adcCtx.state == ADC_STATE_QUADE_CHANNEL_STAGE_2 && s_adcCtx.convertIndex == 3){
//跳过 index3 (温度传感器)的 ADC 转换并执行 index4 (电池电压)的转换。
S_adcCtx.convertIndex = 4;
}
//选择 ADC 输入通道
p_hard_api->SelectADCCompBInput (s_adcConvertChannel[s_adcCtx.convertIndex]);
if (s_adcCtx.convertIndex)
{
//生成手动触发器
HWREG (AUX_ANAIF_BASE + AUX_ANAIF_O_ADCTRIG)= 0;
}
//清除中断标志
HWREG (AUX_EVCTL_BASE + AUX_EVCTL_O_EVTOMCUFLAGSCLR)|=(AUX_EVCTL_EVTOMCUFLAGSCLR_AUX_ADC_IRQ | AUX_EVCTL_EVTOMCUFLAGSCLR_AUX_ADC_DONE);
HwiP_clearInterrupt (INT_AUX_ADC_IRQ);
}
感谢您的支持。
此致、