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.

LM4F120H5QR: TimerSynchronize causes imprecise data bus error

Other Parts Discussed in Thread: TM4C1233H6PM

Hello,

i'm using a LM4F120H5QR rev A3 to run two timers in pwm mode and one in peridioc mode. When i try to synchronize them at some later time (timers running fine for several cycles) via

            TimerSynchronize(TIMER0_BASE,TIMER_0A_SYNC|TIMER_0B_SYNC|TIMER_1A_SYNC)

i get an imprecise data bus error reported by the FAULTSTAT register. I read the errata and put 0-write to the sync-register before and after the sync call, but no effect.

Is this a bug, or am i doing something wrong?

Regards

Roger John

  • Roger,

    Please add the code you are using to initialize the timers, I'll look into it.

    -Austin

  • Hi,

    my code is a bit scattered. First i do this:

        SysCtlPeripheralEnable(PWM_TIMER_PERIPH);
        SysCtlPeripheralEnable(PWM_TIMER_A_PIN_PERIPH);
        SysCtlPeripheralEnable(PWM_TIMER_B_PIN_PERIPH);
        GPIOPinConfigure(PWM_TIMER_A_PIN_CFG);
        GPIOPinTypeTimer(PWM_TIMER_A_PIN_BASE, PWM_TIMER_A_PIN);
        GPIOPadConfigSet(PWM_TIMER_A_PIN_BASE, PWM_TIMER_A_PIN,
                GPIO_STRENGTH_8MA_SC, GPIO_PIN_TYPE_STD);
        GPIOPinConfigure(PWM_TIMER_B_PIN_CFG);
        GPIOPinTypeTimer(PWM_TIMER_B_PIN_BASE, PWM_TIMER_B_PIN);
        GPIOPadConfigSet(PWM_TIMER_B_PIN_BASE, PWM_TIMER_B_PIN,
                GPIO_STRENGTH_8MA_SC, GPIO_PIN_TYPE_STD);
        TimerDisable(PWM_TIMER_BASE, TIMER_BOTH);
        TimerConfigure(PWM_TIMER_BASE,
                TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PWM);
        TimerControlStall(PWM_TIMER_BASE, TIMER_BOTH, true);
        HWREG(PWM_TIMER_BASE + TIMER_O_TAMR) |= (TIMER_TAMR_TAMRSU
                | TIMER_TAMR_TAPLO | TIMER_TAMR_TAILD);
        HWREG(PWM_TIMER_BASE + TIMER_O_TBMR) |= (TIMER_TBMR_TBMRSU
                | TIMER_TBMR_TBPLO | TIMER_TBMR_TBILD);
        TimerLoadSet(PWM_TIMER_BASE, TIMER_BOTH, samplePeriod - 1);
        TimerMatchSet(PWM_TIMER_BASE, TIMER_BOTH,samplePeriod/2 - 1);
        TimerEnable(PWM_TIMER_BASE, TIMER_BOTH);

    where PWM_TIMER_BASE, etc. are set to TIMER2_BASE and corresponding peripheries. After that i do

        SysCtlPeripheralEnable(CTRL_TIMER_PERIPH);
        TimerDisable(CTRL_TIMER_BASE, TIMER_BOTH);
        TimerConfigure(CTRL_TIMER_BASE,
                TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC);
        TimerControlStall(CTRL_TIMER_BASE, TIMER_A, true);
        TimerControlTrigger(CTRL_TIMER_BASE, TIMER_A, true);
        TimerLoadSet(CTRL_TIMER_BASE, TIMER_A, samplePeriod/SW_AVERAGING - 1);
        TimerEnable(CTRL_TIMER_BASE, TIMER_A);

    CTRL_TIMER is TIMER3 and also used as adc trigger (with sw-averaging, 16 in my case). The code works so far, that is i can adc-sample two pins with sw-averaging and output there value via pwm to two other pins using these timers. To get better control over the pass-through delay i wanted to synchronize them, and tried this by a call through an uart command interface (so long after init):

        TimerSynchronize(TIMER0_BASE,
                PWM_TIMER_A_SYNC | PWM_TIMER_B_SYNC | CTRL_TIMER_SYNC);
        TimerSynchronize(TIMER0_BASE, 0); // errata 9.1

    Thanks for your help!

    Roger


  • Hi,

    any progress yet? Is it a hw problem?

    I have yet another question related to this:

    Is it somehow possible to also sync SysTick with the other timers?

    I prefer SysTick since i don't need to bother with interrupt status and clearing which costs precious cylces.

    Currently i do it by waiting for a wrap of the control timer and then reset systick, but that is only accurate to about 70 cycles. I can compensate that manually to 5 cycles, but is there a more precise alternative?

    Regards

    Roger

  • @ Roger,

    Mon ami - has not yet reached one month - be assured that you're, "in the que!"  (critical "rebrand" likely has "all hands on deck...")

    "PWM_TIMER_A_PIN_PERIPH" first of many!  From where did you acquire this?   Just ran "Search in Files" {program code and includes} - and this was nowhere to be found!  As stated - I find/note many other of your parameters to be "inventive" - but unfindable on my system.

    Might you be using a very aged version of StellarisWare?   Ours is 9453 - last one before its unwelcome "replacement."

    I have some slight record of solving such issues - but if I can't "find in files" - I'm unable to load & test your key code...

    Update: Just searched for your 1st four parameters - Result the same, "Found 0 instances - searched in 50 files!"

        SysCtlPeripheralEnable(PWM_TIMER_PERIPH);
        SysCtlPeripheralEnable(PWM_TIMER_A_PIN_PERIPH);
        SysCtlPeripheralEnable(PWM_TIMER_B_PIN_PERIPH);
        GPIOPinConfigure(PWM_TIMER_A_PIN_CFG);

  • Roger,

    Sorry for the delay, somehow I lost track of this thread and am just now being updated about posts.

    Would you please post the code you are running. As it is I cannot evaluate the code you sent me because of all the missing aliases. i need the full code so i can copy / paste / run it, otherwise i  cannot validate your issue.

    FYI the new part number for the lm4f120H5QR is TM4C1233H6PM.

    -Austin

  • Must challenge your use of "aliases."  Years back - we were taught that these make sense when replacing, "hard to understand names/defines."   Yet the "standard" chosen by LMI for StellarisWare (as listed w/in sysctl.h) seems in no such need of any improvement!  (presented here)

    #define SYSCTL_PERIPH_TIMER0    0x10100001  // Timer 0
    #define SYSCTL_PERIPH_TIMER1    0x10100002  // Timer 1
    #define SYSCTL_PERIPH_TIMER2    0x10100004  // Timer 2
    #define SYSCTL_PERIPH_TIMER3    0x10100008  // Timer 3

    I find especially suspect your creation/use of:

        SysCtlPeripheralEnable(PWM_TIMER_PERIPH);
        SysCtlPeripheralEnable(PWM_TIMER_A_PIN_PERIPH);
        SysCtlPeripheralEnable(PWM_TIMER_B_PIN_PERIPH);

    Does not StellarisWare fully/properly enable "both" sub-timers A & B - with its standard call?   SYSCTL_PERIPH_TIMER0

     Suspect the "monkey motion" of changed (and lesser) parameter defines yields little benefits - and complicates any "remote" assistance...  (last assertion - twice in evidence - today...)

  • Hi,

    sorry, here is a stripped version that i verified to jump into hard fault handler after sync:

    6320.main.c
    #define PART_LM4F120H5QR
    #define TARGET_IS_BLIZZARD_RA2
    #include "inc/hw_gpio.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_timer.h"
    #include "inc/hw_sysctl.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/timer.h"
    
    #define SAMPLE_PERIOD 2560
    #define PWM_TIMER_PERIPH SYSCTL_PERIPH_TIMER2
    #define PWM_TIMER_BASE TIMER2_BASE
    #define PWM_TIMER_A_SYNC TIMER_2A_SYNC
    #define PWM_TIMER_B_SYNC TIMER_2B_SYNC
    #define PWM_TIMER_A_PIN_PERIPH SYSCTL_PERIPH_GPIOB
    #define PWM_TIMER_B_PIN_PERIPH SYSCTL_PERIPH_GPIOB
    #define PWM_TIMER_A_PIN_CFG GPIO_PB0_T2CCP0
    #define PWM_TIMER_B_PIN_CFG GPIO_PB1_T2CCP1
    #define PWM_TIMER_A_PIN_BASE GPIO_PORTB_BASE
    #define PWM_TIMER_B_PIN_BASE GPIO_PORTB_BASE
    #define PWM_TIMER_A_PIN GPIO_PIN_0
    #define PWM_TIMER_B_PIN GPIO_PIN_1
    
    #define CTRL_TIMER_PERIPH SYSCTL_PERIPH_TIMER3
    #define CTRL_TIMER_BASE TIMER3_BASE
    #define CTRL_TIMER TIMER_A
    #define CTRL_TIMER_SYNC TIMER_3A_SYNC
    
    void initPWM(void) {
    	MAP_SysCtlPeripheralEnable(PWM_TIMER_PERIPH);
    	MAP_SysCtlPeripheralEnable(PWM_TIMER_A_PIN_PERIPH);
    	MAP_SysCtlPeripheralEnable(PWM_TIMER_B_PIN_PERIPH);
    	MAP_GPIOPinConfigure(PWM_TIMER_A_PIN_CFG);
    	MAP_GPIOPinTypeTimer(PWM_TIMER_A_PIN_BASE, PWM_TIMER_A_PIN);
    	MAP_GPIOPadConfigSet(PWM_TIMER_A_PIN_BASE, PWM_TIMER_A_PIN,
                GPIO_STRENGTH_8MA_SC, GPIO_PIN_TYPE_STD);
    	MAP_GPIOPinConfigure(PWM_TIMER_B_PIN_CFG);
    	MAP_GPIOPinTypeTimer(PWM_TIMER_B_PIN_BASE, PWM_TIMER_B_PIN);
    	MAP_GPIOPadConfigSet(PWM_TIMER_B_PIN_BASE, PWM_TIMER_B_PIN,
                GPIO_STRENGTH_8MA_SC, GPIO_PIN_TYPE_STD);
    	MAP_TimerDisable(PWM_TIMER_BASE, TIMER_BOTH);
    	MAP_TimerConfigure(PWM_TIMER_BASE,
                TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PWM);
    	MAP_TimerControlStall(PWM_TIMER_BASE, TIMER_BOTH, true);
        HWREG(PWM_TIMER_BASE + TIMER_O_TAMR) |= (TIMER_TAMR_TAMRSU
                | TIMER_TAMR_TAPLO | TIMER_TAMR_TAILD);
        HWREG(PWM_TIMER_BASE + TIMER_O_TBMR) |= (TIMER_TBMR_TBMRSU
                | TIMER_TBMR_TBPLO | TIMER_TBMR_TBILD);
        MAP_TimerLoadSet(PWM_TIMER_BASE, TIMER_BOTH, SAMPLE_PERIOD - 1);
        MAP_TimerMatchSet(PWM_TIMER_BASE, TIMER_BOTH,SAMPLE_PERIOD/2 - 1);
        MAP_TimerEnable(PWM_TIMER_BASE, TIMER_BOTH);
    }
    
    void initCtrl(void) {
        MAP_SysCtlPeripheralEnable(CTRL_TIMER_PERIPH);
        MAP_TimerDisable(CTRL_TIMER_BASE, TIMER_BOTH);
        MAP_TimerConfigure(CTRL_TIMER_BASE,
                TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC);
        MAP_TimerControlStall(CTRL_TIMER_BASE, CTRL_TIMER, true);
        MAP_TimerControlTrigger(CTRL_TIMER_BASE, CTRL_TIMER, true);
        MAP_TimerLoadSet(CTRL_TIMER_BASE, CTRL_TIMER, SAMPLE_PERIOD - 1);
        MAP_TimerEnable(CTRL_TIMER_BASE, CTRL_TIMER);
    }
    
    int main(void) {
    	long l = 0;
    	MAP_SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
    	initPWM();
    	initCtrl();
    	while(l++<1000) {
    	}
    	HWREG(TIMER0_BASE + TIMER_O_SYNC) = PWM_TIMER_A_SYNC | PWM_TIMER_B_SYNC
    				| CTRL_TIMER_SYNC;
    	HWREG(TIMER0_BASE + TIMER_O_SYNC) = 0; // errata 9.1
    	while(1) {
    	}
    }
    

    As i try to sync via direct register access, i doubt it is the driverlib (my sample should run from ROM though).

    Thanks,

    Roger

  • From your initial post:

    TimerSynchronize(TIMER0_BASE,TIMER_0A_SYNC  |TIMER_0B_SYNC | TIMER_1A_SYNC)

    Suspect that final "TIMER_1A_SYNC" does you in - as it is "outside" TIMER0_BASE !

    And - does not latest/greatest (code update) continue this misuse?

    HWREG(TIMER0_BASE + TIMER_O_SYNC) = PWM_TIMER_A_SYNC | PWM_TIMER_B_SYNC
        | CTRL_TIMER_SYNC;  // *** You define this as  TIMER_3A_SYNC which is not allowed w/in "TIMER0_BASE"

    And pardon - but as I earlier "alerted" - your use of Alias has rendered you especially susceptible to this error!  (Timer_3A_Sync stands out - Ctrl_Timer_Sync "hides!"  (and kills you in the process!)

    Easy/quick test - remove the non-Timer0 mention.   Yours is a very basic MCU - if time allows - I'll test on more advanced M4 - see if it is possible to "sync" across multiple Timers...   *** we SYNC like this - all the time when using multiple (REAL) PWM Generators - which unfortunately were not included w/in stripped-down lunchpad...

    And - real detail - this function - resides w/in driver.lib - timer.c  (extracted here)

    void
    TimerSynchronize(unsigned long ulBase, unsigned long ulTimers)
    {
        //
        // Check the arguments.
        //
        ASSERT(ulBase == TIMER0_BASE);

        // Synchronize the specified timers.
        //
        HWREG(ulBase + TIMER_O_SYNC) = ulTimers;
    }

    Thus - hoped for sync appears confined to single Timer module (which includes two (A & B) Timers)...  QED...

    What we expect you want - instead - appears here:

        // Synchronize the time base of the generators.
        //
        ROM_PWMSyncTimeBase(PWM0_BASE, PWM_GEN_0_BIT | PWM_GEN_2_BIT | PWM_GEN_3_BIT);

    And these PWM Generators do not reside w/in launchpad MCU!   We exploit this "sync" to control BLDC motors - requiring 3 phase sync...

    Your kindness in awarding, "Verify Answer" gratefully received/appreciated.   (perhaps equally for detail along w/speed of response)

    Update: Thinking a bit more (prior to lunch) have pretty much devised a scheme in which you CAN synchronize across multiple Timers.  Will hold that till you comment upon effort herein expended...

  • Hi, i need TIMER2 because of the gpio pins, TIMER0/TIMER1 control an rgb led on the board.

    I also had a look at the driver lib code before and noticed that you may only use TIMER0_BASE for sync (other will generate precise fault, if  remember right).

    But as the datasheet for the LM4F120H5QR states there is only one sync register for all timers, and it must be accessed via TIMER0_BASE, so this should work (otherwise it would be useless: the A/B-timer from a single module can be activated simultaneously, so no need to sync them).

  • Might you humor me w/test as suggested?   (remove non Timer0 listing w/in "TimerSynchronize() function" - see if we can at least get that function to work)

    KISS works for us - doing too much often yields delay/frustration...

    BTW - lack of appreciation (after such long delay by vendor) is not especially motivating.  (this reporter/others...)

  • Well, when using Timer0, syncing of its two sub timers works. But that is uninteresting. It should work across different timer modules.

    Out of curiosity i tried the same with Timer2 and its sub timers - it works when using TIMER2_BASE for the sync!

    But: This should not work, as the datasheet rev. D states on page 694: "This register is only implemented on GPTM Module 0 only."

    Anyway, that does not solve my problem. I must synchronize different timer modules. Note that the datasheet also states on the following pages, that all timer modules can be triggered with this one sync register of Timer0. (Btw. they changed the part number, but not the data sheet). So it should be possible. Guess it is a hardware issue.

    Update: I tried changing it in my main code too - it works! Well, not really, but i does not generate inprecise busfaults any more. Scope reveals that different timer modules are still not synced. Maybe one timer module can only sync its own timers. But what does page 694ff in the datasheet than mean?

  • Roger John said:
    its two sub timers work. But that is uninteresting

    Well then - myself/other "helpers" will be sure to confine our efforts only to those unresolved issues which you judge "interesting."  (but not in this life-time...)

    Fact in evidence - I diagnosed and cured your original Fault issue, "TimerSynchronize causes imprecise data bus error" - to no thanks and nominal interest... 

  • To interested others:

    Our Stellaris M4 MCU - more advanced than that on the launchpad - includes Register, "GPTMSYNC" - which via quick read does seem to support "sync" across multiple, unrelated Timers. Note: have yet to load, run, confirm...

    This Register (which may not exist - all M4 MCUs) suggests that a single, properly crafted write - may cause a, "timeout event" across multiple timers.  (and one hopes - "Multi-Timer Sync" results:...)

  • cb1_mobile said:

    Well then - myself/other "helpers" will be sure to confine our efforts only to those unresolved issues which you judge "interesting."  (but not in this life-time...)

    Oh yes, please, don't hesitate, not for me.

    cb1_mobile said:

    Fact in evidence - I diagnosed and cured your original Fault issue, "TimerSynchronize causes imprecise data bus error" - to no thanks and nominal interest... 

    No, you did not. When you read my initial post, you will see that this thread is about synchronizing two different timer modules. An answer like "well, then just use one" is perhaps nice since it clears the imprecise fault, but it is not the solution to my problem. So - no, sorry, sometimes it is more than just the heading.

    Btw., advertising a higher mcu is also not very kind. I doubt you will send me one for evaluation, will you? Nevertheless the mcu i have is perfectly sufficient for my needs, i don't need another. All i ask for is clarification why my mcu does not work as i expect it to work according to the datasheet, and if i can do something about it.

    Thanks.

  • The Register I described (and detailed via diagram) earlier as, "GPTMSYNC" is in fact the, "TIMER_O_SYNC" Register - just as described by this requesting poster.  The current data manual for our LM4F (actually LX4F, still!) appears older - thus behind - both our paid IAR IDE and Rev 9453 StellarisWare.  And this before the rebrand monkey motion...

    Here are key defines - extracted from our mcu.h file:  (again an LX4F - 64 pin - w/full PWM Gen capability)

    // The following are defines for the bit fields in the TIMER_O_SYNC register.
    //
    //*****************************************************************************

    #define TIMER_SYNC_SYNCT0_TATB  0x00000003  // A timeout event for both Timer A
                                                // and Timer B of GPTM 16/32-Bit
                                                // Timer 0 is triggered

    #define TIMER_SYNC_SYNCT3_TA    0x00000010  // A timeout event for Timer A of
                                                // GPTM 16/32-Bit Timer 3 is
                                                // triggered

    And - if we can believe the description which accompanies the "GPTMSYNC" Register - it should be possible to achieve SYNC across multiple (i.e. Timer_N, Timer_N+1 etc.) MCU Timers - via a single write to the (more properly named)  TIMER_O_SYNC Register. 

    Whether this desired capability has truly been implemented - cannot yet say/confirm.  As/if time allows - will try this on our "more heavyweight" M4 MCU - and report.

    (there was no "advertising" of that "heavier" MCU - that is simple reality - like you - I'm user of vendor's devices - as/if/when they meet price/performance/reliab. targets...)

    Poster's most recent code:

     HWREG(TIMER0_BASE + TIMER_O_SYNC) = PWM_TIMER_A_SYNC | PWM_TIMER_B_SYNC
        | CTRL_TIMER_SYNC;
     HWREG(TIMER0_BASE + TIMER_O_SYNC) = 0; // errata 9.1

    should be reviewed to see if parameters comply w/data imported from our MCU.h file.  (again - different MCU - but much is identical)  As our group is unlikely to ever use poster's MCU - have not reviewed any MCU errata - which may impact this effort...

     

  • Hm, i think i found the problem. Feels like face palm.

    So, the LM4F really has only one GPTMSYNC register, which belongs to Timer0 as the datasheet states, and all syncing has to be done through it.

    But of course, to use it, its timer module Timer0 has to be activated. While this might be no problem in most cases, it was in mine since i did not use Timer0 because of gpio. I admit that i did not see this causal dependence at first (i thought the register was shared between all timers, and therefore powered by any active timer). A note in the datasheet might be helpful.

    My code now works after inserting the power-up command for Timer0. So note to myself: On next occurrence of imprecise bus fault, check if the device being accessed is actually powered.

    I still wonder why i didn't see this in my sample code. I could swear i tested it with timer0, and it crashed. But maybe that was a stall program flash.

    So thanks to all participants for their efforts. And sorry for my blindness.

    Happy coding!

    Regards

    Roger

  • Roger John said:
    works after inserting the power-up command

    By "power-up" - might you mean, "SysCtlPeripheralEnable()?"  (or some "sleep related" derivative?)

    Applaud your persistence and awareness/consideration in posting findings - sure to benefit others.

    If you "enable conversations" (via forum set-up) - like to contact you in that manner...

     

  • Yes, exactly. It seems confusing though to activate a timer module which you don't need for timing but only for syncing. A separate module which gets activated automatically when any timer is activated would have been nicer, but now that i know, it is ok.

    I have done so, feel free to contact me.

  • Roger John said:
    seems confusing...to activate a timer module which you don't need for timing

    Indeed - suspect designers "expected" that Timer_0 would "always" be in play.  (and - if that proved your case - we'd not have your solution so noted)

    Contact launched (via cb1) as indicated...