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.

CCS/TM4C123GH6PM: uDMA transfers same value twice from the GPTMTBR register when triggered by capture event

Part Number: TM4C123GH6PM
Other Parts Discussed in Thread: SEGGER

Tool/software: Code Composer Studio

Hello,

My application is supposed to implement a velocity measurement by counting the amount of clock ticks elapsing between pulses coming in from a linear encoder (1nm indications coming in at approximately 50 000Hz). The way I do this is to configure the timer for input edge time mode where the timer reacts for every positive edge of the encoder pulses coming in at CCP1 and saves a snapshot value of the GPTMTBV register to the GPTMTBR register, repeating this for every encoder pulse. At the same time the uDMA is configured to be triggered by the capture event in the timer to transfer the value of GPTMTBR to a memory array buffer that I have defined to save the encoder timings. 

The problem I am having is that I see that the same integer value is repeated twice sometimes in my memory buffer, almost like the encoder pulses has come in twice before the clock has counted one cycle, which should be impossible with a 80MHz clock. Without knowing exactly what caused this I cannot know exactly how to handle the velocity measurement at this moment. 

I am grateful for all help I can get. The code is included bellow: 

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "inc/hw_timer.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
#include "driverlib/timer.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/interrupt.h"
#include "m_wide_timer5.h"
#include "driverlib/udma.h"


#include "../m_interupt_priorities.h"

uint8_t pui8DMAControlTable[1024];
//#define timerSource ((uint32_t *) WTIMER5_BASE + 0x04C)
uint32_t pui32DestBuffer[DMATransferSize]; // DMATransferSize = 100
uint32_t numberOfTickPerIntervall;




//using this timer to sample the velocity of the z-direction
void
wideTimer5IntClear(void)
{
	TimerIntClear(WTIMER5_BASE, TIMER_TIMB_DMA);

}

void wideTimer5Int(void){

    wideTimer5IntClear();
   // wideTimer5Off();
    memset(pui32DestBuffer, 0, sizeof(pui32DestBuffer));
    uDMAChannelTransferSet(UDMA_CHANNEL_I2S0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC,( (void *) (WTIMER5_BASE + TIMER_O_TBR)), pui32DestBuffer, DMATransferSize);
    uDMAChannelEnable(UDMA_CHANNEL_I2S0TX); //restarts the dma transfer



}

//*****************************************************************************
//
//Initiate timer
//
//*****************************************************************************
//


void wideTimer5Init(void (*pfnHandler)(void))
{
    numberOfTickPerIntervall = INT32_MAX;


    HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    HWREG(GPIO_PORTD_BASE + GPIO_O_CR) |= 0x80;
    HWREG(GPIO_PORTD_BASE + GPIO_O_AFSEL) &= ~0x80;
    HWREG(GPIO_PORTD_BASE + GPIO_O_DEN) |= 0x80;
    HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = 0;
    SysCtlPeripheralReset(SYSCTL_PERIPH_WTIMER5);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER5); // enable the periphiral and pins for the timer
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_WTIMER5))
    {
    }
   // TimerDisable(WTIMER5_BASE, TIMER_BOTH);
    GPIOPinConfigure(GPIO_PD7_WT5CCP1);
    GPIOPinTypeTimer(GPIO_PORTD_BASE, GPIO_PIN_7);
    wideTimer5Off();
    TimerConfigure(WTIMER5_BASE, (TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_ONE_SHOT | TIMER_CFG_B_CAP_TIME_UP));
    TimerControlEvent(WTIMER5_BASE, TIMER_B, TIMER_EVENT_POS_EDGE);
    TimerLoadSet(WTIMER5_BASE, TIMER_A, numberOfTickPerIntervall);
    TimerLoadSet(WTIMER5_BASE, TIMER_B, numberOfTickPerIntervall);

//***************************************************************************************************************************************

    //configure the DMA to transfer data about the timing of the encoder ticks
    SysCtlPeripheralReset(SYSCTL_PERIPH_UDMA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA))
    {
    }

    uDMAEnable();

    TimerDMAEventSet(WTIMER5_BASE,TIMER_DMA_CAPEVENT_B); //sets the capture event to trigger a dma request

    uDMAChannelAssign(UDMA_CH29_WTIMER5B); // so that the dma recieves data from wtimer5
    uDMAControlBaseSet(pui8DMAControlTable);
    uDMAChannelControlSet(UDMA_CHANNEL_I2S0TX, UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_ARB_1);
    uDMAChannelTransferSet(UDMA_CHANNEL_I2S0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC,( (void *) (WTIMER5_BASE + TIMER_O_TBR)), pui32DestBuffer, DMATransferSize);

    //Interrupt to restart the counting when the buffer has filled up
    wideTimer5IntClear();
    TimerIntRegister(WTIMER5_BASE, TIMER_B, pfnHandler);
    IntPrioritySet(INT_WTIMER5B, INT_PRIO_WTIMER5);

   // enable everything
    TimerIntEnable(WTIMER5_BASE,TIMER_TIMB_DMA);
    TimerEnable(WTIMER5_BASE, TIMER_BOTH);
    uDMAChannelAssign(UDMA_CH29_WTIMER5B); // so that the dma recieves data from wtimer5
    uDMAChannelEnable(UDMA_CHANNEL_I2S0TX);

   // extern bool uDMAChannelIsEnabled(uint32_t ui32ChannelNum);


}

void
wideTimer5On(void)
{
    TimerEnable(WTIMER5_BASE, TIMER_B);
}

void
wideTimer5Off(void)
{
	TimerDisable(WTIMER5_BASE, TIMER_B);
}

  • My firm uses similar (expected modern, magnetically based) encoders.       Might you identify yours - just in case we too - stock it?

    BTW - your post is nicely composed - and well presented - although I 'must' take issue ... w/some of  your  'claims and/or reportings.'     (you did request - 'All the help you can get!')

    My major issues:

    • Your encoder is (possibly/likely) one from 'Heidenhain'  (LC Series) which may resolve a 'step'  to 1nm.     (0.001µm)     Might you confirm?
    • You wrote, 'Saves a snapshot value of the GPTMTBV register to the GPTMTBR register.'     I believe that's highly mistaken - the 'BR' Register is the one which CAPTURES the, 'Edge Time Counter Value' - in sync. with your signal's rising edge!    In contrast - the 'BV' Register is 'free running' - you've allowed it to REPLACE (by over-writing) the (proper) 'BR' Register - in my opinion!     The edge-Timer function has automated the detection process - placing the detected edge w/in - Register 'BR.'     Your job then - is to read & store Register 'BR' and NOT to overwrite it - w/contents from the free-running, 'BV' Register...
    • If my analysis (above) proves correct (gleaned from my read of the MCU Manual - and the simply 'terrific' - figure 11-4, pg 715) then your job reduces to, 'Reading & Storing the 'BR' value - prior to the (expected) arrival of the (very) next positive signal edge!
    • The 'delta' between successively captured 'BR' Register Values - notes the elapsed time between positive edge arrivals - and may be employed to aid your calculation of, 'Linear Velocity.'
    • You note an 80MHz System Clock - but does not 'Edge Time' impose a, "Divide by FOUR" limitation upon such, 'edge detection?'     (from memory - that's 2 clock stability - enforced upon (both) rising & falling edges - yielding such divide by 4 - which degrades edge detection to a 20MHz (MAX) clock rate!)
    • Now you note a  ~50KHz  pulse rate - from your linear encoder.     Is that (really) the case (seems VERY low) - and over all linear spans/movements   - in (both) directions - and 'especially' during 'high-speed' accelerations?    Today's modern 'Motion Control Systems' boast, 'Meter of  'Precise Travel' in ~(few hundred) mS!'     If my (back of the envelope) calcs are correct - your Encoder's reporting:  '1nm travel in 20µS'  - extends to,   '1mm of potential travel - requiring 20 SECONDS!'     Can that (really) be your systems's objective?      (it is noted that even a slow, 3-legged Turtle, could (easily) 'Win such a race!')       (And - 'velocity' - may shift to 'glacial'.)

    Might I suggest your employment of 'KISS' - which would seek, 'Small Steps' - aimed at incremental confirmation of code & device success - via systematic & (logically) sequential  test/verification.     (i.e. one very well defined, small (measurable) test-step - at a time!)

    Use of the µDMA - this EARLY w/in your investigatory process - surely/substantially  violates KISS!      (adding greatly to your diagnostic effort)    

    • Instead - can you not trigger a scope to capture a short sequence of encoder pulses (perhaps just 4) - and then compare/contrast the scope's 'edge capture' ...  vs. that reported by your NON-µDMA (simpler) MCU (small) buffer 'BR' Register capture & store?)      (do prevent the over-write of 'BR' by 'BV'!)
    • When (and IF) such 'dual sourced' results  converge - then & only then - can  'far greater confidence' in measurement accuracy arrive! 
    • My suspicion is that your 'issue' may range (beyond) - 'simple duplication' of the 'Edge Timer's captured value...'

    And again - if you identify your encoder - and we stock it (we've many from (Heidenhain, RLS, others) - we may be able to 'duplicate your testing...'     (although at  VASTLY GREATER - Linear Motion Displacements...)

  • Hello,

    I did indeed ask for all help I can get and I thank you for your time!

    1. My encoders are Renishaw Atom linear encoders with a resolution of 1nm. 

    2. I think we mean the same thing, what I meant was that the timer automatically captures the time of the rising edge of the signal. I have also understood it that this time that the timer captures in BR is a snapshot of the BV  register at the moment of the rising edge.

    3. That has been my analysis as well, but maybe the uDMA was too big of a step all at once. Either way I would need the uDMA eventually since I cannot have an interrupt every time I get a encoder pulse. But until the final implementation I suppose a more rigorously validation of the capture event would be needed as you say.

    4. This is indeed how I calculate velocity.

    5 and 6. The aim is to travel at the speed of 50 000 nm/s which is very slow I know. This is why I did not see the clock being too slow for pulses coming in at such a low pace. Worth mentioning is that the wagon of who we are measuring the speed of is floating on air-bearings and the speed was recorded when the wagon was was not affected by any intentional external forces except for the vibrations of the room of course. 

    I am inclined to agree that the problem might span beyond the duplication of BR values, but there is indeed something suspicious with the fact that the BR and the uDMA gives the same value for two subsequent elements in the Destination buffer. 

    Either way, I will attempt to compare a simpler non- uDMA method of capturing BR register with an implementation using the built in QEIVelocityGet.

     

  • Thank you - always good to receive (some) response (positive or negative) in behalf of time/effort expended.    (in poster's behalf)

    Once more - to my mind - you are 'Rejecting KISS' - this time in favor of the 'Multi-Step, more complex' QEI Module.   

    Your proposed use of 'µDMA & the QEI Module' are proper - yet again - they add NEW Elements - which (may) complicate, delay - even confound your objective.     (I 'built from scratch' - then took a tech firm 'Public'  - by 'committing to KISS!'     (and today - most always - we are called to 'rescue' those - w/a penchant for, 'too much - too soon!'      (yet this 'flawed/imperfect desire' - keeps  our  doors OPEN...)

    May I note (again) - the great power of your 'employing my suggestion' of  your,  'Seeking Result CONVERGENCE!'      (Scope cap - vs. MCU 'BR' Store (Not BV)  - as clearly detailed - my initial post)

    Another "KISS approved" test methodology would have you (for now) replace your encoder with a, 'Controllable Pulse Generator' - and drive the Timer's input w/that.     (insure that your signal meets all MCU specs)     It is suspected that the encoder adds complexity/unknowns - which are quickly & easily removed - via this 'KISS based' (i.e. far superior) methodology.

    An extremely 'quick/easy'  Means of 'Generating such 'encoder replacement/mimic'ed signals' - is via (another) MCU Timer - ordered into PWM Mode (set to progressively higher 'test' frequencies - yet maintaining 50% duty cycle) and then 'interconnecting that (new) Timer Output to your original Timer's input...'    (thus enabling your KNOWN input signal arrival rate - and removing (any) encoder 'irregularity!')       (which explains  ...  why I 'get the big bucks!')

    Due to the 'extreme environmental nature' of  your application - it proves best (by far) to, 'Properly test & confirm your MCU implementation FIRST - and  ONLY AFTER Proven Success (and then & only then) - introduce the (precision & complex) encoder.'      (I just KNOW that you  STILL  (are drawn) to the 'all in one approach' - yet the method detailed herein - is INSTEAD - 'KNOWN & PROVEN to WORK!')     (while 'harvesting' MANY key/critical 'data points' (blunted via the 'all in one')  ...  thus unwise to summarily reject!)

    (btw - Renishaw acquired 50% of RLS - it (may) prove useful to 'compare/contrast' an RLS magnetic encoder (more robust perhaps)  - as well...)    

  • Hello again,

    I think that the idea with mimicking the encoder pulses with a more reliable source is a good idea, I have however validated the encoder before, but it is worth testing. 

    So far I tested with removing the uDMA and generate an interrupt each time I get an encoder pulse to store the BR value for velocity calculation. I still saw the tendency to get two subsequent BR values to be exactly the same. I did unfortunately not see a convergence of the QEI module and the velocity generated by the BR values, but this might be expected since we get very different sampling periods between the two methods. 

  • And the suggested use of a 'Scope' - to capture & store those 'encoder edge events'  - has been rejected for 'what reason?'

    It is the 'CONVERGENCE' of that  'Scope Captured, encoder edge arrivals' - and your logged (again) 'BR-ONLY' MCU Store - which I believe of (pardon) FAR GREATER VALUE!    (when contrasted to (less direct/informing) 'QEI vs. BR values.')

    'Validated the encoder before' - provides (little) diagnostic aid - here & now.   (i.e. zero insight into the methodology of such (past) 'validation.')
    It is believed that 'following the instructions presented' (several times, now) will quickly & best, 'Resolve your issue.'

    I've answered your request as best I can - may I note that what you list as a 'good idea' is in fact - 'a well-practiced/oiled and 'long PROVEN' successful method!'     (clearly deserving of,  "This resolved my issue.")

  • Hi CB1,

    I have been forum searching "JTAG Locking" for some research into TM4C boards, therefore your posts are on nearly every thread which I found related to the topic. I just wanted to thank you for all you effort explaining and helping others by providing valuable information gleaned from years of experience. I was going to LIKE several of your posts but...\o/ This is the best I can do. With a Segger's J-Link and a KISS any future projects will be smooth sailing. Thank you.
  • My friend - WOW!   (my check (as earlier promised - 'In the mail') ...  must have arrived - SOONER  than expected!)
    And your (rare) yet much appreciated posting - surely has, 'Justified such Payment!'       (Now - Staff & I (really) must SELL something...)

    Smooth Sailing cannot (always) be expected - a more reasonable outcome ... 'Smoother Sailing' - and 'Less Frequent Entry' into 'Known & Avoidable' DEAD-ENDS!    (Plague-Istors (R9,R10) - anyone?)      Along w/your (mentioned) J-LINK & the extraordinary 'KISS' - do consider the pro IDE 'IAR' - available as a FREE Download.    Note that 'J-LINK & IAR' - enable ALL VENDORS' ARM MCUs!     (Free IAR limited to 32KB - which (surprisingly) proves an ADVANTAGE - as that  ENCOURAGES - KISS!    (ONE SMALL, MEASURABLE Battle  at a time ... can I sell - or what?)

    Thank you for your kind words - the  'unreasoned/inexplicable' BANISHMENT of 'LIKE' - has caused me to (substantially) EXIT this forum.    In honor of U.S. Independence Day (and staff exhaustion/vacation) I returned to the (banishment) scene - but  just for a fleeting moment...

    Best to you and again thanks.     (do cash that check quickly - and well-earned!...)