This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
a customer needs to set up the ADC to be triggered either by timer or by SW. They keep the timer always running. When they want to trigger by SW in between, they disable conversion, re-configure for SW trigger, and enable conversion again, which works great.
However, when switching back to HW trigger, the ADC starts conversion immediately, it seems that the timer has signaled an event to trigger the ADC in the meantime, this trigger is queued and serviced immediately when the ADC conversion is enabled again.
How can the queued trigger event be cleared before enabling the ADC conversion again?
BR,
Philipp
I would recommend to do it like this: When they want to trigger by SW, stop the timer and they disable conversion, re-configure for SW trigger. When switching back to HW trigger, clear the counter of the timer and re-start it.
Hi Gary,
this is not an option as the timer serves for other purposes as well. What other options can we recommend?
BR,
Philipp
Sorry for the later response. If you can't stop the timer, I think you can try to clear the specific trigger event in ICLR register by API named DL_Timer_clearInterruptStatus(); that you used to trigger the ADC to do conversion.
Hi Gary,
using DL_Timer_clearInterruptStatus() clears the RIS bit for CPU event (interrupt), but leaves RIS bit of generic event route untouched. In this case, it's the zero-event of the timer. With this bit still set, the timer event still serves as ADC trigger.
Any other ideas?
BR,
Philipp
Oh sorry provide the wrong API, it should be this one DL_Timer_clearEventsStatus()
Hi Gary,
as discussed offline, please find attached the files that I used for my tests.
/* * Copyright (c) 2020, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "ti/driverlib/dl_timerg.h" #include "ti_msp_dl_config.h" volatile bool gCheckADC; volatile uint16_t gADCResult[4]; int main(void) { SYSCFG_DL_init(); NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN); NVIC_EnableIRQ(TIMER_1_INST_INT_IRQN); gCheckADC = false; DL_ADC12_disableConversions(ADC0); DL_ADC12_initSeqSample( ADC12_0_INST, // Init configuration for ADC DL_ADC12_REPEAT_MODE_DISABLED, // Sampling mode: Single, do not repeat DL_ADC12_SAMPLING_SOURCE_AUTO, // AUTO mode required for configuration of sampling time DL_ADC12_TRIG_SRC_SOFTWARE, // TODO: Use timer event //DL_ADC12_TRIG_SRC_EVENT, // Conversion is started by Hardware trigger - Valid event configuration is required DL_ADC12_SEQ_START_ADDR_00, // Start address of sequence DL_ADC12_SEQ_END_ADDR_04, // End address of sequence DL_ADC12_SAMP_CONV_RES_12_BIT, // Resolution of ADC DL_ADC12_SAMP_CONV_DATA_FORMAT_UNSIGNED); // Data format of the result - Unsigned, right aligned DL_ADC12_enableConversions(ADC12_0_INST); DL_TimerG_startCounter(TIMER_0_INST); DL_TimerA_startCounter(TIMER_1_INST); __WFI(); while (false == gCheckADC) { __WFE(); } gADCResult[0] = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0); gADCResult[1] = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_1); gADCResult[2] = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_2); gADCResult[3] = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_3); __BKPT(0); while (1) { __WFI(); } } void ADC12_0_INST_IRQHandler(void) { switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) { case DL_ADC12_IIDX_MEM3_RESULT_LOADED: gCheckADC = true; break; default: break; } } void TIMER_1_INST_IRQHandler(void) { /* DL_Timer_clearInterruptStatus(TIMER_0_INST, GPTIMER_CPU_INT_IMASK_L_SET | GPTIMER_CPU_INT_IMASK_Z_SET); */ DL_Timer_clearEventsStatus(TIMER_0_INST, DL_TIMER_EVENT_ROUTE_1, DL_TIMER_EVENT_ZERO_EVENT); DL_TimerG_stopCounter(TIMER_0_INST); DL_Timer_clearEventsStatus(TIMER_0_INST, DL_TIMER_EVENT_ROUTE_1, DL_TIMER_EVENT_ZERO_EVENT); DL_ADC12_disableConversions(ADC0); DL_ADC12_initSeqSample( ADC12_0_INST, // Init configuration for ADC DL_ADC12_REPEAT_MODE_DISABLED, // Sampling mode: Single, do not repeat DL_ADC12_SAMPLING_SOURCE_AUTO, // AUTO mode required for configuration // of sampling time // DL_ADC12_TRIG_SRC_SOFTWARE, // TODO: Use timer // event DL_ADC12_TRIG_SRC_EVENT, // Conversion is started by Hardware trigger - // Valid event configuration is required DL_ADC12_SEQ_START_ADDR_00, // Start address of sequence DL_ADC12_SEQ_END_ADDR_04, // End address of sequence DL_ADC12_SAMP_CONV_RES_12_BIT, // Resolution of ADC DL_ADC12_SAMP_CONV_DATA_FORMAT_UNSIGNED); // Data format of the result - // Unsigned, right aligned DL_ADC12_enableConversions(ADC12_0_INST); }
BR,
Philipp
It seems some wrong with the event trigger module, I got a workaround for this issue that when you modify the ADC's trigger source modify the timer's event publish channel ID, for example the normal timer event publish ID is 1, when you switch ADC trigger source to software you change the timer's event publish ID to 0 as below
DL_ADC12_disableConversions(ADC12_0_INST);
ADC12_0_INST->ULLMEM.CTL1 &= ~(ADC12_CTL1_TRIGSRC_MASK);
DL_TimerG_setPublisherChanID(TIMER_0_INST, DL_TIMER_PUBLISHER_INDEX_0, 0);
DL_ADC12_enableConversions(ADC12_0_INST);
And when you want to switch ADC trigger source to hardware you need to change the timer's event publish ID to 1
DL_ADC12_disableConversions(ADC12_0_INST);
DL_TimerG_setPublisherChanID(TIMER_0_INST, DL_TIMER_PUBLISHER_INDEX_0, 1);
ADC12_0_INST->ULLMEM.CTL1 |= ADC12_CTL1_TRIGSRC_MASK;
DL_ADC12_clearInterruptStatus(ADC12_0_INST,0xFFFFFFFF);
DL_ADC12_enableConversions(ADC12_0_INST);