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.

TM4C123GH6PM: Interrupt priority in TM4C123

Part Number: TM4C123GH6PM

Hello,

I am trying to get the FXOS8700 accelmag and FXAS21002 gyro to work with the TM4C123 mcu. So far, I wrote the i2c driver, made the sensor initialize generating interrupts, and handle those interrupts and read data from i2c. What happens is, if I configure the code to work with only one sensor, it works, but if I have two interrupts, after a while (like 30-60seconds) one of the interrupt handling mechanisms fail.

Here are the relevant parts of the code:

    // gyro interrupt pin setup
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, GPIO_PIN_4);
    GPIOPadConfigSet(GPIO_PORTC_BASE, GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
    GPIOIntDisable(GPIO_PORTC_BASE, GPIO_PIN_4);
    GPIOIntClear(GPIO_PORTC_BASE, GPIO_PIN_4);
    GPIOIntRegister(GPIO_PORTC_BASE, gyro_isr);
    GPIOIntTypeSet(GPIO_PORTC_BASE, GPIO_PIN_4, GPIO_FALLING_EDGE);
    GPIOIntEnable(GPIO_PORTC_BASE, GPIO_PIN_4);

    // accelmag interrupt pin setup
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_2);
    GPIOPadConfigSet(GPIO_PORTE_BASE, GPIO_PIN_2, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
    GPIOIntDisable(GPIO_PORTE_BASE, GPIO_PIN_2);
    GPIOIntClear(GPIO_PORTE_BASE, GPIO_PIN_2);
    GPIOIntRegister(GPIO_PORTE_BASE, accelmag_isr);
    GPIOIntTypeSet(GPIO_PORTE_BASE, GPIO_PIN_2, GPIO_RISING_EDGE);
    GPIOIntEnable(GPIO_PORTE_BASE, GPIO_PIN_2);

PC4 is configured for a falling edge, and PE2 is  configured for rising edge, which are connected to the sensor board, and gyro is configured to generate active 0 output (for falling edge) and accelmag board is configured to generate active 1 output.

// gyro interrupt service routine
void gyro_isr(void) {
    if(GPIOIntStatus(GPIO_PORTC_BASE, false) & GPIO_PIN_4) {
        GPIOIntClear(GPIO_PORTC_BASE, GPIO_PIN_4);
        gyro_data_ready = true;
    }
}

// accelmag interrupt service routine
void accelmag_isr(void) {

    if(GPIOIntStatus(GPIO_PORTE_BASE, false) & GPIO_PIN_2) {
        GPIOIntClear(GPIO_PORTE_BASE, GPIO_PIN_2);
        accelmag_data_ready = true;
    }
}

Here are the interrupt handlers. They just mark a volatile boolean so that I can read the sensor from the main loop.

In my main loop, I check for these booleans anrd read data:

    while(1) {

        //current_time = nh.now();

        if(gyro_data_ready) {
            GyroGetData(FXAS21002C_ADDRESS, &gyroRD);
            gyro_data_ready = false;
        }

        if(accelmag_data_ready) {
            AGGetData(FXOS8700_ADDRESS, &accelRD, &magRD);
            accelmag_data_ready = false;
        }
    }

No matter what I tried, I could not get rid of this bug. The active high interrupt for the accelmag, gets stuck at 1, meaning that the sensor was not read (which would have cleared the interrupt on the sensor)

At the beginning I was thinking this was related to the FXOS8700 accelmag orFXAS21002 gyro sensor, but at this point I believe this is interrupt related. Somehow, the sensor rises interrupt line, but the interrupt does not trigger, because other interrupt is happening. To support this theory:

A. By examining the both interrupt lines with scope carefuly, (by videotaping it) I have evidence out that misfunction happens when two interrupts are triggered at the same time.

B. I replaced the failing accelmag interrupt from PE2 to PB4. This time the other interrupt line at PC4 fails (from the gyro)

Here is the link to the video:  twitter.com/altineller/status/1170381044115283973 (I had to put it on twitter because appearently vimeo does not like scope shoots)

Any ideas, help and recommendation on the problem greatly appreciated.

Best Regards,

Can

  • HI,

      I see that you use GPIOIntStatus(GPIO_PORTC_BASE, false) as well as in the other interrupt where you try to get the raw interrupt status. Why don't you use GPIOIntStatus(GPIO_PORTC_BASE, true) instead? With that said, I don't think it is the cause of your problem.

      I will suggest you try something like below. Do so for the other ISR as well. What this will do is to make sure the clearing of the flags is fully complete before exit out of the ISR. There could be a race condition such that you exit the ISR but the flag is not yet clear. When this happens, the ISR is immediately entered again indefinitely. If this change does not make a difference, we need to investigate other probable causes. 

    void gyro_isr(void) {
        if(GPIOIntStatus(GPIO_PORTC_BASE, false) & GPIO_PIN_4) {
            GPIOIntClear(GPIO_PORTC_BASE, GPIO_PIN_4);
            gyro_data_ready = true;
        }
        GPIOIntStatus(GPIO_PORTC_BASE, false); // make sure this is not optimized out
    }
    // accelmag interrupt service routine
    void accelmag_isr(void) {
        if(GPIOIntStatus(GPIO_PORTE_BASE, false) & GPIO_PIN_2) {
            GPIOIntClear(GPIO_PORTE_BASE, GPIO_PIN_2);
            accelmag_data_ready = true;
        }
    GPIOIntStatus(GPIO_PORTE_BASE, false); // make sure this is not optimized out, check the disassembly code
    }
  • My small group 'likes' vendor's Charles analysis.     (yet somehow - cannot 'find' the *LIKE* button - which has 'led the way' for the demise of  (even) these MCU's names.)    

    This theory of ours springs from: 'personal preference' as well as 'bitter experience.'

    We avoid - whenever/wherever possible - the use of a 'Logic High' to serve as 'Active Signal Level.'   This due to possible 'overly high impedance' as well as the higher likelihood for signal 'uncertainty' and/or 'glitching.'    And indeed - most external sources are more capable & efficient - at providing 'Logic Low' as the 'Active Signal Level.'

    Now note your issue (first description):   (directly quoted from poster)

    • accelmag board is configured to generate active 1 output.
    • The active high interrupt for the accelmag, gets stuck at 1 

    Note that it is 'unclear' as to the meaning of, 'interrupt for accelmag - stuck at 1.'   Does this mean that the signal level latches - constantly at logic high?    Perhaps we missed it - but nowhere is it explained - just how the 'Active Sensor Interrupt Signal' is Toggled OFF/Inactive.    That's important - is it not?

    Watching an (unknown) video is 'disallowed' for my group - cannot a series of scope caps (properly & convincingly) present the 'Active State of both sensor signal lines?'    (some consideration must be granted to helpers...)

    can altineller said:
    I replaced the failing accelmag interrupt from PE2 to PB4. This time the other interrupt line at PC4 fails (from the gyro)

    We like this idea - and are 'clueless' as to how 'Accelmag' NOW performs - and PC4 fails!    We REALLY need to SEE your exact code - post that change - which yielded so unexpected a result.    (we had a 'vague' idea that the 'ordering' of your interrupt servicing - may prove causative (only the first one was 'seen/felt' by the MCU - after sufficient 'time had elapsed.'

    Always of concern - unwanted (unrecognized) competing connections (past 'hangers on') to your interrupt pins - inadequate power - and suspect connections (especially ground - ALWAYS ground) to your remote sensor boards.    Excessive wire/cable length also is damning - no such advisement has been provided...

    Final note - our preference most always is for 'Adding the Interrupt Vectors' to the Interrupt Table - resident w/in the 'Start-Up' file.   While remote - your 'registering of these interrupts' - creates the possibility of 'Stack Overflow' - while gaining you (little) (i.e. nothing, really) in the process...

  • Hello cb1_mobile,

    'The active high interrupt for the accelmag, gets stuck at 1' means I have configured the accelmag sensor to generate an active high interrupt, and it goes high, but mcu does not read the sensor, so it stays high.

    I do love hearing about your 'personal preferences' and 'bitter experiences'. Thank you.

    Adding:

        IntPrioritySet(INT_GPIOC, 0x00);
        IntPrioritySet(INT_GPIOE, 0x01);

    Resolved the problem. But I see that my design has many flaws from your post. I have few questions:

    a. Instead of registering interrupt vectors, I should put them to startup_ccs ?

    b.For one of the sensors I am using falling edge, and the other rising edge. I should have them both falling edge? (active low)

    c. if I have two high priority interrupts, I should put them on different ports, (like PB, PC) or i should maybe use 2 pins of same port

    Also, I the purpose of this code is for an open source imu sensor to use with ros. I was going to put it on github after it is running perfectly, but I just uploaded it now so you can have a look: github.com/fximu/FXIMU

    It is basically a 400hz imu sensor, that attaches to ROS, parameters can be configured with .yaml files, and a python script that republishes the data to /imu/data topic after correcting for soft and hard iron errors and gyro offsets. It just does it so that you can launch ros imutools package to use madgwick or complementary filters (github.com/ccny-ros-pkg/imu_tools)

    Best regards, and thank you.

    Can

  • Thank you - yours is a nice & detailed follow-up.    (Young staff here always groans when posters 'take a week' to respond - claiming 'busy.')   

    Who is NOT Busy - and it is those (really) 'busy' who 'somehow'   (i.e. via DISCIPLINE/DESIRE)  ALWAYS RESPOND!'

    Now we do 'take some issue' w/your writing, "gets stuck at 1' means I have configured the accelmag sensor to generate an active high interrupt, and it goes high, but mcu does not read the sensor, so it stays high."     Pardon - but just, "HOW does the accelmag sensor (or any sensor - for that matter) KNOW that it has been 'read?"     (which you suggest - will 'unstick it!')     It is expected (instead) that a separate 'mechanism' (one beyond a simple 'read') IS required.   (i.e. a toggled signal line etc.)     Might you further clarify?

    To your points - I'm not in agreement that the addition of, "IntPrioritySet()" - by itself - led to your program's success.   (this due to the fact that the code ran:

    • fine when only a single sensor was deployed
    • also ran fine (for the first minute or so)

    and in (both) cases - "IntPrioritySet()" was (then) ABSENT!    (at least - not included and/or hinted at - w/in your postings!)

    Now to your specific issues/questions:

    a) my firm uses IAR - suggest that you 'NAME & PLACE' each interrupt vector's NAME (properly) w/in your IDE's Start-Up file - and then create (using that name) the Interrupt Service Routine (ISR) placed w/in a suitable position (outside of main) w/in your general code.    Surely you can find 'code examples' which detail this process.   (it IS hard - until you see it done correctly - just once!)

    b) indeed - falling edge - active sensor output LOW - proves best/safest (earlier post justified such choice)

    c) 'KISS' directs that you encourage simplicity - thus 'select  each interrupt pin from 'separate ports' - at least initially.    Once (really) working - you may 'experiment' w/placing them on the same port - and then 'evaluating' that (same port) interrupt - to determine the (real) source.    But do that later - long after you've confirmed REAL Success.    

    Pardon - but again we are 'in doubt' of your 'fix' via the single addition of "IntPrioritySet()."

    Staff is curious as to 'how you chose' those particular sensors.   There is HIGH Sensor Activity - especially by 'giants' - and the performance level is continually rising.    It would appear that a, 'General (near universal) Sensor Accommodation' would be 'Highly Marketable & Desirable!'    The ability to compare Sensors: 'A vs. B vs. C' with the minimum of 'fuss/bother' - would prove a superior path...  (when compared to a 'single-source sensor' - which is unlikely to prove, 'Top Dog!')

  • Hello,

    It seems that I jumped to conclusion too early. IntPriorySet() has not fixed the problem. It would just fail in couple of minutes, now it takes longer time to fail.

    Here is the clarification for sensors clearing interrupts: Once the sensor gets configured to generate data ready interrupt by sending a value to its related control register, the int pin on the sensor will go high (for active high configuration) and stay high until the data is requested from the sensor tru i2c, once the read is complete the sensor will make the int pin go low. Basically reading the sensor tru i2c will make the int pin on sensor side go inactive. The statements GyroGetData, AGGetData clears the int pins. If the data read is not performed, the sate of int output pin does not change.

            if(gyro_data_ready) {
                GyroGetData(FXAS21002C_ADDRESS, &gyroRD);
                gyro_data_ready = false;
            }
    
            if(accelmag_data_ready) {
                AGGetData(FXOS8700_ADDRESS, &accelRD, &magRD);
                accelmag_data_ready = false;
            }

     I am not aware of any special mechanism, or register write on the sensor chip to clear the interrupt, but I shall double check this from the datasheet.

    How I choose those sensors: brute force. I have been testing these sensors for a long time adxlxxx, mpu6050,9150,9250,9255, bno055. The last one was bno055 and it was supposed to have a onboard DMP (digital motion processor, fancy word for onboard filtering) - but unfortunately it did not work with the tm4c123 due to i2c clock stretching issue. Then I evaluated the sensor with an Arduino, and noticed that it is really noisy, and drifty. At this point I decided to use a non-DMP sensor, and do the filtering myself. 

    It is said that this gyro sensor has very little zero-rate drift, which is important for making orientation calculations. The sensor vendor claims that it has 10-20 times less noise. So I bought the sensor, and tested it (with complementary filtering provided by ROS) and it really performs much better than the previous sensors that I tested. (when I say tested, I mean plug it into a visualization system and looked at things like drift, repeatability, etc, I have not flown/driven it or any real test like that.)

    github.com/fximu/FXIMU/tree/master/launch/compare.launch file launches two different ros filters, complementary and madgwick, (taking data from the same sensor and publishing the results) and github.com/fximu/FXIMU/blob/master/launch/rviz/imu_complementary.rviz file is an rviz config file that will launch rviz and show the output for both results by means of 2 little right hand arrow thingies, so one can study differences between filters, sensors, etc.

    At this point the problem continues. I will try to put the two sensors on different i2c buses, and see if it makes a difference, and see if any additional steps are required to clear interrupt from the sensor side from the data sheet.

    Best regards.

    Can

  • Hello,

    Do you recommend adding GPIOIntStatus(GPIO_PORTE_BASE, false); as the last statement in the ISR? Or is it the GPIOIntClear(GPIO_PORTE_BASE, GPIO_PIN_2); that will clear the flags?

    Because:

    void accelmag_isr(void) {
        if(GPIOIntStatus(GPIO_PORTE_BASE, false) & GPIO_PIN_2) {
            GPIOIntClear(GPIO_PORTE_BASE, GPIO_PIN_2);
            accelmag_data_ready = true;
        }
    GPIOIntStatus(GPIO_PORTE_BASE, false); // make sure this is not optimized out, check the disassembly code
    }

    The GPIOIntStatus() is already called inside the if statement. So it would execute a second time.

    Also I used GPIOIntStatus(GPIO_PORTC_BASE, falsewhich would give raw interrupt status, because it was like that in the interrupts example. I did look at the documentation for gpiointstatus but I have not clearly understood what is a raw status vs masked status.

    Also how do I make sure that the second statement does not get optimized out?

    Best regards,

    C.

  • cb1_mobile said:
    I'm not in agreement that the addition of, "IntPrioritySet()" - by itself - led to your program's success. 

    Let the record show that 'crack staff' got (at least one) diagnosis right!      Alas - tomorrow is a school day - thus (proper) celebration must be placed on 'hold.'

    Your initial post stated that, 'All was well' when only a single sensor was employed.     However - might that also prove, 'Not the case' - as the failure simply takes longer to reveal?     It remains difficult to imagine how the 2nd device's addition - by itself - leads to failure.    (unless of course insufficient power or connection gremlins occur.)

    Earlier you noted that - at times - both sensor interrupts occurred together.    And under that condition - the 'Accelmag's interrupt output signal becomes 'latched high.'   To me - that points especially to some code defect - occurring when you 'transact' w/that sensor - upon receiving the interrupt signal.    To become perfectly clear - is it true that each sensor provides an 'Interrupt Output signal' - along w/the serial communication channels?   

    If this issue was mine - I'd proceed as follows:'

    • Switch and/or configure the accelmag sensor to produce an 'active low' interrupt output signal 
    • Employ that sensor - alone - and develop a program which repeatedly 'transacts' w/that sensor.    This should produce a large number of successful sensor transactions.   Capture one complete transaction - being sure to 'catch both' the sensor's entire signal output AND your MCU's 'talk-back.'   Ideally this is done w/a scope-cap - which can be displayed here.
    • Once that's achieved add the 2nd sensor - and employ your best efforts to, 'Capture the accelmag's & your MCU's signal transactions - during failure.   
    • The comparison of the transactions - 
      • working accelmag sensor (i.e. operated by itself)
      • vs. failing accelmag sensor (likely caused by the addition of the 2nd sensor)

    should provide the required insight into, 'What, Where & How' the failure was introduced.    You must insure that ALL sensor specifications are being met - especially those involving signal timing & duration.  

  • Hi Can,

      The GPIOIntClear is to clear the flag. When it is called, it writes  a '1' to the flag (implemented in flip flop). The GPIOIntStatus() is to read the flag. The read cannot happen until the write is complete. This means the GPIOIntStatus() will confirm if the flag has been successfully written. You can assign the return value of the GPIOIntStatus to a variable and compare it to an expected value before you exit the ISR. Again, as I said, I don't know if this is the root cause of the problem. If it does not work then it is another problem to investigate.

  • Hello Charles,

    I did try:

    // gyro interrupt service routine
    void gyro_isr(void) {
        if(GPIOIntStatus(GPIO_PORTD_BASE, true) & GPIO_PIN_3) {
            GPIOIntClear(GPIO_PORTD_BASE, GPIO_PIN_3);
            gyro_data_ready = true;
        }
        GPIOIntStatus(GPIO_PORTD_BASE, false);
    }
    
    // accelmag interrupt service routine
    void accelmag_isr(void) {
        if(GPIOIntStatus(GPIO_PORTB_BASE, true) & GPIO_PIN_5) {
            GPIOIntClear(GPIO_PORTB_BASE, GPIO_PIN_5);
            accelmag_data_ready = true;
        }
        GPIOIntStatus(GPIO_PORTB_BASE, false);
    }

    unfortunately it did not fix the problem. I am using gcc, and I dont know how to make it sure that the last line from each isr does not get optimized out, but I am guessing because the first GPIOIntStatus has different parameters,  it will not.

  • Hi Can,

      Can you show a scope cap of the Acc when its interrupt pin is asserted and the I2C bus when the MCU is supposed to perform the read? How do you know that the MCU never read the data? A scope cap will be handy to verify? I will also suggest that you set another GPIO pin inside the Acc ISR. You can clear the pin after you exit the ISR. This will let us know at the very last successful Acc interrupt assertion if the ISR is entered. Basically in your scope cap, you should show that at every rise edge of the interrupt pin, there is another rise edge with some cycles of delay on the GPIO pin. If there is a rise edge on the interrupt pin and the interrupt pin remains high forever but you also see a GPIO pin edge then this will prove that the ISR is entered. The investigation should lead to the I2C bus. If you never see a GPIO pin edge after the interrupt pin becomes flat line then it is the ISR never entered. 

  • Hello Charles,

    I have changed the intterrupt handlers to:

    // gyro interrupt service routine
    void gyro_isr(void) {
        MAP_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, GPIO_PIN_2);
        if(GPIOIntStatus(GPIO_PORTD_BASE, true) & GPIO_PIN_3) {
            GPIOIntClear(GPIO_PORTD_BASE, GPIO_PIN_3);
            gyro_data_ready = true;
        }
        GPIOIntStatus(GPIO_PORTD_BASE, false);
        MAP_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0x00);
    }
    
    // accelmag interrupt service routine
    void accelmag_isr(void) {
        MAP_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3);
        if(GPIOIntStatus(GPIO_PORTB_BASE, true) & GPIO_PIN_5) {
            GPIOIntClear(GPIO_PORTB_BASE, GPIO_PIN_5);
            accelmag_data_ready = true;
        }
        GPIOIntStatus(GPIO_PORTB_BASE, false);
        MAP_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0x00);
    }

    So everytime the ISR is entered I get a small spike in the scope.

    I also hooked up a logic analyzer and captured both interrupt lines, both PA2,PA3 for the seeing the spikes, as well as I2C0[SCL,SDA] and I2C3[SCL,SDA]

    (I am using i2c0 for one sensor and i2c3 for the other)

    The top 4 (D0 to D3) is the gyro sensor, D0: interrupt D1: PA2, D2: SCL3, D3: SDA3

    The bottom 4 (D4 to D7) is the accelmag sensor, D4: interrupt, D5: PA3, D6: SCL3, D7: SDA3

    This is just where the accelmag sensor stops responding, near to the end, the interrupt line falls at D4, you see the spike at D5, and I2C data transfer takes place, but the interrupt line is never de-asserted again.

    I am using two seperate boards [adafruit.com/product/3463], from one i just use the gyro, from the other accelmag only. [I did this so I could hook them on different i2c buses] - but they also have different voltage regulators, both being fed from the 5V on the tm4c123 launchpad.

    Also a sub-question: is using 2 i2c buses for 2 different sensors a good idea? I thought it was but as seen from the scopecap they can never be on at the same time.

    Best regards,

    Can

  • Greetings,

    Your effort is well-thought, properly detailed & impressive.     Good job!      As so often stated here (by vendor & 'others') the use of an instrument which can 'see & capture' Serial-Bus Activity - proves (almost) mandatory.     And is ALWAYS helpful.

    I believe that you've well followed vendor's Charles guidance - and the screen cap is extremely helpful.    That said - a question arises - it being, "Why is there an (apparent) 'Delay' - imposed upon the gyro-sensor's 'SCL & SDA's' signal output (top traces) (post its interrupt toggle ('H' -> 'L'))?    Note that 'No such delay' (or a far smaller one) arrives w/the accel sensor!

    Might that (apparent) delay - imposed upon the gyro sensor's I2C transactions - result from the 'switch-over' from one I2C channel to the second?    It is believed the actual code is required for such analysis.    (and thinking (out loud) further - there may exist, 'No such switch-over' - each 'unique' I2C transaction will occur upon its (own) I2C bus - which has (already) been set-up & configured.)

    Thinking further - 'Part deux' - might the accel sensor demand an 'extension' (i.e. be 'multi-byte') which would explain its increased duration?    (when compared to the 'briefer' gyro sensor.)

    Follows several observations/comments - for your consideration:

    • Might that result from the (assumed) Logic Analyzer's 'Trigger' (if one) - being 'keyed to D4' (the accel sensor's) interrupt line?
    • Accel sensor's I2C transactions appear to 'persist longer' than those of the gyro sensor.    Is that expected?
    • The 'width' of the accel sensor's interrupt signal (when active) appears smaller than that of the gyro sensor
    •  No/Zero 'difference' in signaling is evident leading up to - or during - the fateful/final accel-sensor transaction.    (where it 'hangs')

    Here's a visual (super-imposed upon your original) - highlighting the (apparent) 'hold-off' of the gyro-sensor's I2C signals.    Such 'hold-off' is either, 'Non-existent' or too minimal to note - upon the accel-sensor!   (and again - this may be a 'trigger' issue ... yet such 'Should be noted!')

    can altineller said:
    is using 2 i2c buses for 2 different sensors a good idea?

    I would vote, 'Yes' - as this is in compliance w/the (always helpful) 'KISS.'   (Simplify, Tightly Focus - Make the 'most basic' implementation work - only (then) and systematically - add refinements...)

  • Hi cb1,

      Thank you! You have asked all the good questions that I want to ask too. 

    Hi Can,

      From what I can see, the MCU seems to behave as expected. It is the last I2C transaction you need to investigate. What command was sent to the Acc sensor? Is it a valid/correct command?

      In the various prior posts you said that the Acc generates an interrupt on the rise edge. Why both the Gyro and Acc generate interrupt on the falling edge as appeared on your LA capture. 

      How much current does your two sensors consume? You might want to monitor the power supply to the Acc sensor.

      

  • Charles Tsai said:

    Hi cb1,

      Thank you! You have asked all the good questions that I want to ask too. 

    Dreaded insomnia arrived 2 hours later than yesterday!     Thanks for your kind words.     And kindly note - I directed that poster change to 'Active Low' interrupts (i.e. his earlier accel irq) - as they are (usually) stronger (lower Z) and that is far more, 'normal/customary.' 

    Now as for 'good questions'  -  perhaps I'll agree - yet there exists a 'BEST Question' - and that is clearly 'YOURS!'    (staff suggests that cb1 return to earlier career as 'Sailing Instructor' - as we own the boat and (anyone) could 'Run Aground 3 times' - and be 'Chased from the sea' by the coast guard!)    [neither the L.A. coast guard - nor my (current) parole officer - 'like' me...]

    Charles Tsai said:
    What command was sent to the Acc sensor? Is it a valid/correct command?

    Poster's capture reveals the dual 'Signal Flows' - yet does not present the (potentially) necessary - Signal DETAIL.     And as you well noted - an 'illegal' command (is much like 'Running one's Sailboat Keel' into the ground) - and is almost certain to produce 'negative effects!'     (damn depth finder 'shares' the blame)

    It may also (maybe) be of interest to learn, 'Where in the sequence (i.e. number of) accel-sensor transactions - does failure occur?    If that proves (near) consistent - that (may) be another clue - and we need as many as possible...    (between your 'BIG Brain' and mine (crack staff describes as 'Dull-Normal') we should have, 'Had this guy 'On the Air' - many posts ago...  'WGN' is a cb1 firm client)

  • Hello Can. You maybe want to take a closer look to the 6.16 paragraph, page-47, of NXP's datasheet of FXAS21002C Rev. 2.1, 5/2015 and also consider/play with FIFO's status register before & after reading. Try to make the reading work inside the ISR and avoid using global variables. Test this with both interrupts in use.  I hope this may help. Good luck. [Are you using pull-ups on the INT pins?]

    John

  • Hello John,

    Some time has passed - hope all 'goes well' for you/yours.

    Now the poster's issue is with his 'ACCEL Sensor' - not the gyro sensor!    (it is believed that you focused upon the gyro sensor!)

    can altineller said:
    I am trying to get the 'FXOS8700' accelmag and FXAS21002 gyro to work with the TM4C123 mcu.

    Both devices 'stray' from normal/customary as they provide I2C AND a separate 'Interrupt Output' signal.    Poster has described the interrupt signal as 'Active' - which (usually) suggests it (may) escape the need for pull-up augmentation.    By the 'sharp edges' his screen cap reveals - I believe there is a reasonable chance that those interrupt signals are 'push-pull' - and  escape the requirement for pull-ups.

  • Hello cb1. Hope & wish everything is also great for you all. Sometimes the case may be that the behaviour of one device somehow perturbates the operation of the other. Also I do not usually trust, unless a microOS is present, the use of global variables from inside INTs/ISRs. I had got some pain in the past because of this. I suggested pull-ups because sensors and μC are on different boards, but you're probably right on what you say. All the best. 

    John  

  • Greetings,

    One further attempt to 'further whip' this dead/dying horse.     Note that neither my firm's staff nor I have ever used (or knew of) either of poster's external devices.

    Now my design expert friend from Greece (John P.) thought that the problematic 'accel sensor' interrupt could require a 'pull-up.'    Yet - while that's possible the image staff  captured  (presented below)  notes that 'Push-Pull' is the default output configuration.    (requires no pull-ups!)

    I don't know what the 'other' responders here believed - but my sense was that the 'Interrupt Signal' from the sensor - was 'little more' than a 'handshake.'    And that proves a rather large, mistaken belief.     This particular sensor boasts a 116 page data manual - and over 20 pages - include references to 'interrupts.'     Note too - this sensor employs TWO Interrupt Outputs - further complicating 'design-in.'    Thus it is (now) clear - interrupts & their design, handling & sequencing - prove a (very) Big Deal.    (and that was not previously noted...)     And was (unlikely) to be revealed w/poster's 'Over-Reliance' upon (another firm's) code development - more 'copied' than 'understood.'

    May it now be noted - there IS an 'Elephant in this room!'     Vendor's MCU is (almost surely - Yes - Bet the Farm) 'Off the Hook.'     All evidence points to 'Sensor Issue(s) and/or understanding!'     I will make this final attempt to 'Further Guide this poster' - but clearly - the Sensor firm should be properly engaged - and (somewhat) 'Share the Work-Load!'    (Take-Over - really.)

    That said - what follows (may) blunder into a solution.   (one hopes)

    • Interrupts are 'tied' to unique sensor registers, functions & behaviors.
    • To clear the interrupt (may) require that the answering 'MCU read'  -  very correctly clear one or several (critical) sensor register bits - and these vary w/function.
    • Thus it may be that the 'failing sensor interrupt' (i.e. interrupt sticks) (may) be due to an 'incorrect and/or incomplete Sensor Read!'
    • Thus far - the data which accompanied (any/all) of the 'Failed Sensor Reads' (causing the interrupt to 'stick') - has not been revealed.
    • A (very) simple test (cb1's preferred test) would see our poster, 'Only repeat those accel sensor transactions which past worked!'     (i.e. change nothing!)    Should this I2C transaction (repetition) - succeed in 'preventing 'Sticky Interrupts'  -  then it is likely that, 'Improper/Failed Sensor Reads' were the cause.     (of 'sticky' interrupts)
    • We would still like 'Poster's opinion' as to the likely cause of the 'Varying Delays noted between Accel/Gyro Sensors' I2C transactions - following interrupts.     Accel  (near zero) - Gyro (large)!   Why?

    Should this systematic method 'fail' - perhaps Los Angeles (does) require 'another' sailing instructor ...   (one equipped w/a 'sensor!'  ... maybe)

  • Hello John,

    I have tried pull up resistors, but it did not change anything.

    Regarding "play with FIFO's status register before & after reading" in the adafruit code for arduino, for this sensor, (in both accelmag, and gyro sensors) there is a part in the code:

    [github.com/adafruit/Adafruit_FXOS8700/blob/master/Adafruit_FXOS8700.cpp] line 235:

      /* Read 13 bytes from the sensor */
      Wire.beginTransmission((byte)FXOS8700_ADDRESS);
      #if ARDUINO >= 100
        Wire.write(FXOS8700_REGISTER_STATUS | 0x80);
      #else
        Wire.send(FXOS8700_REGISTER_STATUS | 0x80);
      #endif
      Wire.endTransmission();
      Wire.requestFrom((byte)FXOS8700_ADDRESS, (byte)13);
    
      /* ToDo: Check status first! */
      #if ARDUINO >= 100
        uint8_t status = Wire.read();
        uint8_t axhi = Wire.read();
        uint8_t axlo = Wire.read();
        uint8_t ayhi = Wire.read();
        uint8_t aylo = Wire.read();
        uint8_t azhi = Wire.read();
        uint8_t azlo = Wire.read();
        uint8_t mxhi = Wire.read();
        uint8_t mxlo = Wire.read();

    Before read, it does send something, however I did not exactly understand. wire.write(.. is sending REGISTER_STATUS value 0x80. ?

    It exists in both gyro and accelmag sensors. (sending register_status | 0x80) 

    I did try to replicate it in my code by sending AG_REGISTER_STATUS, 0x80 - but it did not change anything as well.

    Best regards.

    Can

  • Might you 'take a look' at the posting ~30 minutes prior to yours.    Many facts/findings therein...

  • Hello Charles,

    - I have changed the acc to generate a falling edge interrupt, so the scopecap depicts both gyro and accel as falling edges.

    - The sensors consume in the range of hundreds of microamps depending on the frequency.

    Here is the schematics of the sensor board I am using:

    As seen, it has bidirectional level shifters. I am suspecting maybe these are the cause of the problem. (it is made so the board can be used by people with 5V gpio's)

    I have tried feeding the breakout board with 3v3 from the output of the voltage regulator, thus not using the voltage regulator. It did not change the results.

    Here is a picture of the setup I am using:

    It was on a breadboard, then I decided to hookit up using jumper wires as seen in the picture, so I guess it is better than breadboard noise-wise.

    I already made a pcb board for all this in eagle, waiting to be sent to the pcb production house, but I needed to address this problem before sending it. But now I am suspecting it could be the wiring, or the fact that i2c line is not connected directly to the sensor.

    Best regards,

    Can

  • Hello cb1;

    Here is what I think is happening on the scopecap:

    1. whichever interrupt comes first, triggers an i2c read. here in D4 going low the first time, it triggers an i2c read. notice that since this is the accelmag sensor, and it has 13 bytes to read it takes longer than the interrupt clears. according to datasheet reading the mag registers cause interrupt to deassert, so it does deassert while the i2c transaction is continuing.

    2. while this happening the gyro interrupt comes in at D0. however the i2c transaction will have to wait, as main loop has not finished reading the accelmag.

    3.only after the first i2c read is finished, the gyro read begins. as seen on D2 and D3. As soon as read is finished gyro int is deasserted.

    4. "Accel sensor's I2C transactions appear to 'persist longer' than those of the gyro sensor.    Is that expected?" <- yes, because it is 13bytes.

    Since yesterday I am using only one i2c channel. The problem still persists.

    If operated seperately the gyro has 402.322hz output. (if specified to be 400) the accelmag has 398.812hz output data rate. (if specified to be 400)

    Since gyro outpus at 402 and accelmag at 398, one signal will sweep other, and it will cause a 'hold-off' in an alternating fashion. it is either the gyro keeping the i2c busy, and accelmag has to hold-off, and or the otherway around (accelmag keeping i2c busy, and gyro read has to be hold-off.

    This irregularity in reading could be the cause of the crash.

    I am logging with a software called pulseview, and it can save as .sr files. I could add that as an attachment - or if there is some other way to share long non-png scopecaps I could do that.

    Best regards,

    Can

  • HI Can,

      

    can altineller said:

    2. while this happening the gyro interrupt comes in at D0. however the i2c transaction will have to wait, as main loop has not finished reading the accelmag.

    3.only after the first i2c read is finished, the gyro read begins. as seen on D2 and D3. As soon as read is finished gyro int is deasserted.

      Your analysis is not correct. You are doing your Accel I2C read in the main loop, isn't? When an interrupt from gyro comes in, it will interrupt the Accel read right away. The CPU is not going to wait for the 13 bytes in the Accel to complete before it jumps to the gyro ISR. You could potentially have two flags, the gyro_data_ready and accelmag_data_read true at the same time. After the CPU comes out of the gyro interrupt, it depends on how you write your main loop to continue the remaining data read of the Accelmag or the gyro. Very likely your Accelmag read is interrupted in the middle. For example, the Accelmag read is interrupted in the middle of a 7th read before you are interrupted by the gyro. The Accelmag read on the 7th byte is likely to be corrupted. Did you check the I2C transaction as I suggested. Did the sensor even ack'ed the I2C transaction?

  • There is one workaround that I can think of and worth for you to try. That is, before you start to read the data from a sensor, you disable the processor interrupt globally. You only enable the interrupt after you complete the read. For example, before you read the 13 bytes accel sensor data, you will first disable the interrupt in the accelmag ISR and only enable the processor interrupt after the 13 bytes are completely read. Do the same for the gyro too. 

    I think your problem is a classical race condition. You may need to slow down your data rate from 400Hz to some slower speed. Try 200Hz data rate if this is programmable in your sensor and I think it will help your problem. 

  • Hello cb1 & Can. 

    Can, I fully agree with cb1's analysis [He and his firm are very experienced on such issues]. It would worth the try to study in detail the sensor's manual. As it is clearly displayed in my first post, I asked about the pull-ups, but only at the end of my post and inside [..] because I had already seen what cb1 is cleverly underlining in red, (-the remarks regarding INTs under the diagram of the sensor). Sometimes the default initialization source of some examples, like the source you are using, may configure the  registers otherwise than the default. But since you have already used pull-ups to no avail then the solution of the problem may be related to the way INT and FIFO registers are handled by the source, as per my primary suspicions. I do not have in my bins any of the sensors you are using so I can't be of more help right now. I'm also sure that vendor's/poster's MCU is not related at all to the particular technical problem. A final but KISS related suggestion of mine would be to forget the interrupts for a while and do the readings only from inside main_loop() "polling" wise. If that works fine, then sensor's INT registers handling will need a much-much closer study from your part. I suspect the 'devil' is somewhere there hidden :) Good luck again. John

  • Hello Can, Charles & friend/cohort John,         (John - thanks your kind words ... staff assures - your 'check' is 'in the mail')

    Charles - you clearly have gone FAR, 'Above & Beyond' - all here appreciate your investment of time/effort.    Yet it has, 'Yet to be proven that this vendor's MCU - in any way or means - is responsible for such 'Sensor Interrupt Hang.'    In addition - it is the 'sensor alone' which initiates the interrupt - and bears 'full responsibility for its 'return to idle' - upon a (PROPER) [and possibly timely] 'Sensor Read.'     Poster 'Can' provided an insightful 'signal cap' - yet that included 'No Insight' (which I believe to be 'necessary') into the 'actual data sent by the MCU - to achieve a 'Proper/Timely Sensor Read!'     Staff here noted several sensor datasheet mentions of the importance of 'proper sensor reads.'   (i.e. to 'clear' the interrupt)    Such deserves further exploration - and is far outside this forum's (MCU some believe) domain...   

    To your most recent diagnosis - poster just added the following:  (post 11 Sept 18:01 ... that's 6:01p - for those shore-bound)

    can altineller said:
    Since yesterday I am using only one i2c channel. The problem still persists.

    Pardon - but this, 'Shift to a SINGLE SENSOR' likely 'invalidates' the issue of a, 'Race Condition' - perhaps you'll note & agree.

    More & more - while poster is 'wished well' - those @ Adafruit & NXP should devote (some) time & effort - and our 'over-worked' diagnostic crüe freed to enjoy the dying days of summer - and 'released from 'Poster's highly Specific 'SENSOR WARS!)

  • Hello Charles. You're most probably right that Can is been tortured by a INT race condition. Looking at my archives, I found a link from the "arm Community" on the particular issue. How to handle Cortex-Mx INTs, -IF in the case of Can the problem is due to ill behaved INT handling coding. In that post many clever techniques are exposed and also Joseph Yiu does some fruitful proposals on the issue: 

    https://community.arm.com/developer/ip-products/processors/f/cortex-a-forum/4089/cortex-m4-interrupts-behaviour-when-same-interrupt-vector-has-multiple-interrupts

    Hope that will help Can and others as well.

    All the best,

    John

    P.S. Hadn't yet read that even with the use of the one I2C channel the problem persists. So eventually seems that problem's manifestation may be due to inefficient handling of sensor's registers. So it must be solvable.

  • Hello John,

    Timing (as usual) 'is everything.'     You just wrote:

    John Piliounis said:
    Can is been tortured by a INT race condition.

    Yet - as a certain (professional) school taught - one must 'fully, properly - even exhaustively' examine ALL of the Evidence!    (even late breaking evidence!)

    Should you view my post - issued with the EXACT Time Stamp as your own - you will note that Can has switched to Single Sensor - thus the 'Race Condition' (pardon) has 'Raced Downhill as Causal-Nexus' - has it not?     The presence of a smart/gifted/always motivated staff 'heightens' the detection of all evidence - especially that 'late breaking' - and of 'high value!'

  • Hello cb1,

    - I have read the datasheet for the fxos8700cq over and over. There are two interrupt pins, and many int sources. You can select one int source (like data_ready) to be int1 pin, and all the other int sources are or'red to go to the other pin. you can also query sensor to ask what is the source of this interrupt once received.

    I am wondering this: If reading the data from the sensor deasserts the interrupt, will it also affect the timing of the sensor. does the sensor start measuring the next cycle after read is complete, or it asserts interrupt once data_ready, and proceeds to measuring the next cycle. notice at the first case we can use this to synchronize the sensor with other, while in the second case we can not.

    - I configured a timer interrupt set to 400hz, and made the i2c reads from the timer interrupt. It worked no problem, and you can also observe the timings to interrupts that would tell when the data was ready. This could be another approach: basically poll the sensors periodically, taking note at which ns the interrupt was ready, then use this data to calculate dt. I also looked into ros's complementary filter code, to see it actually calculates dt and takes it into account each update.

    - I am making a ccs version of the software, without the ROS library, so I can take advantage of the debugger. Currently, it is compiled with gcc-arm and built with the catkin_make ros tool. I will be trying out what Charles recomended. (disabling the interrupts)

    - I made a posting at the sensor vendors community page.[community.nxp.com/thread/512669] However at this point I probably should update questions, to include questions raised by contributors of this post.


    Best regards,

    Can

  • Yes cb. I had the replying page remaining open for some time and didn't notice the case. I added a P.S.(....)  later in my post. All clear, yet the link is very enlightening I think. Greetings, John

  • Hello,

    When I said using only i2c channel, I meant "I am using same i2c bus for both sensors"

    I have not been able to decode the i2c read and writes - I only have pulseview and sigrok, and a usbee. The last data packet before the death, is a bit different than others. I should find a way to decode that. Do you know of any software/probe package that can do i2c decode? or do we have to go tru that manually?

    All the driver code for this sensor that is published by others do not include interrupts configuration, but free running sensors. I will continue to dig into nxp.

    ~Best

  • Hello Can,

    Thank you - indeed your efforts here have 'notably sharpened' (perhaps credit Charles, John, possibly another) and all here 'Wish you Well.'

    Yet - your issue assumes - more & more - 'Sensor WARS' - and not 'MCU Inadequacy' - it is believed.

    Now I made one suggestion - which gifted staff believes 'first cabin' - and thus far - 'bypassed/ignored.'   

    "Send only that 'Read Answering Data' which has previously 'worked' - send it at a (slower rate) - and repeatedly (w/proper pauses) - and 'Send that ONLY' - nothing else."'

    It is believed that there exists (reasonable) potential for a 'Read Answering Error or Omission' - which results in 'Sensor Hang!'     Sending ONLY 'KNOWN GOOD DATA'  to the sensor (most likely) eliminates such 'error/omission' - unless 'transmission gremlins' rear their 'none too attractive' heads.

    And a HW issue - while your pre-made 'EZ wired connections are attractive' - they are 'too long' for staff's/my taste.   (shorter & direct ALWAYS prove best)    At the minimum - route the SCL signal line as, 'Far from the SDA & INT lines as possible' (to reduce unwanted signal coupling ) - induced/impressed by 'Long, Adjacent, Parallel' wire/cable runs...

  • Ai Yi Yi.    (stronger language (censored/suppressed!)    

    can altineller said:
    When I said using only ONE  I2C channel, I meant "I am using same i2c bus for both sensors"

    That's a 'Dagger' into staff's & my heart - language IS important - and your 'meaning' proved  totally  unexpected!

    You earlier wrote:

    Can Altineller:  "Since yesterday I am using only ONE  I2C channel.   The problem still persists."

    However - your 'sin' (may) have been 'over-stated' - you noted, 'ONLY one I2C Channel' - which entire staff & I - (too quickly) took to mean, 'ONLY ONE SENSOR!'    (in fairness to staff/myself - this thread has been highly focused upon 'TWO 'SENSORS' and  NOT  I2C  Channels!)    
    Thus 'Race Conditions LIVE' - and I seek (another) wall for 'daily head bang.'
  • I apologize, for not being able to express with better precision. I have been working long hours obsessively trying to fix this, and I language skills has degraded.

    I have the code running on ccs now, got rid of all the ros code, and I will try disabling the interrupts while i2c is active.

    By the way the forum software is not doing so well, sometimes I hit reply, and it will not post, etc.

    Best,

    Can

  • Can, to your question: "....or do we have to go thru that manually?..." a possible answer may be: Bit Banging

    Try a continuous polling read and write from inside main loop on one sensor alone, and if all go well,  then on the other sensor alone, and if all go well then on both sensors. If everything works as expected, then try using the interrupts mechanism on a -one-by-one basis and then on both sensors together.

     For the polling R/W tests I would suggest to first check  if any care should be taken for keeping sensors' interrupt mechanisms out of your way so that you you'll have to deal only with I2C sensor's data. That's as far as I can go for the moment. Good luck.

    John

  • Hello again,  

    You 'show up' - prove responsive (but for my 'key' (Send ONLY 'Known Good' Sensor Data) suggestion ) and have made progress - even though the SENSOR WARS issue digs deep.

    'KISS' although (never/ever) 'allowed here' - IS your friend - and your intent (now) to, 'Eliminate ALL Extraneous' - perfectly complies with the KISS initiative.

    Firm/I note the same 'forum SW issue' - thus we always 'compose externally - ALWAYS SAVE - and then 'copy/paste' here'...     (should you not be 'too far' from John - his RF experimentation may prove the cause of (some) of your issues.)      (we have 'tin-hats' on Sale @ discount...)

  • Hello Again,

    void AGGetData(uint32_t ui32WorkerAddress, tRawData *accelRD , tRawData *magRD) {


        uint8_t ui8Data[13];
        I2CAGReceive(ui32WorkerAddress, AG_STATUS, ui8Data, sizeof(ui8Data));

        // copy the 14 bit accelerometer byte data into 16 bit words
        // notice accel data is 14-bit and left-aligned, so we shift two bit right
        accelRD->x = (int16_t) ((ui8Data[1] << 8) | ui8Data[2]) >> 2;
        accelRD->y = (int16_t) ((ui8Data[3] << 8) | ui8Data[4]) >> 2;
        accelRD->z = (int16_t) ((ui8Data[5] << 8) | ui8Data[6]) >> 2;

        // copy the magnetometer byte data into 16 bit words
        magRD->x = (int16_t)((ui8Data[7]  << 8) | ui8Data[8]);
        magRD->y = (int16_t)((ui8Data[9]  << 8) | ui8Data[10]);
        magRD->z = (int16_t)((ui8Data[11] << 8) | ui8Data[12]);

    }

    this is the code for each read. It calls I2CAGReceive, which is:

    void I2CAGReceive(uint32_t ui32WorkerAddress, uint8_t ui32WorkerRegister, uint8_t *pReceiveData, uint8_t ui8NumBytes) {

        // specify that we are writing (a register address) to the worker device
        I2CMasterSlaveAddrSet(I2C2_BASE, ui32WorkerAddress, false);

        // specify register to be read
        I2CMasterDataPut(I2C2_BASE, ui32WorkerRegister);

        // send control byte and register address byte to worker device
        I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_START);

        // wait for MCU to finish transaction
        while(I2CMasterBusy(I2C2_BASE));

        // specify that we are going to read from worker device
        I2CMasterSlaveAddrSet(I2C2_BASE, ui32WorkerAddress, true);

        //if there is only one argument, we only need to use the single send I2C function
        if(1 == ui8NumBytes) {

            //send control byte and read from the register we specified
            I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);

            //wait for MCU to finish transaction
            while(I2CMasterBusy(I2C2_BASE));

            //return data pulled from the specified register
            pReceiveData[0] = I2CMasterDataGet(I2C2_BASE);
        } else  {

            // initiate send of data from the MCU
            I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

            // wait until MCU is done transferring
            while(I2CMasterBusy(I2C2_BASE));

            // return data pulled from the specified register
            pReceiveData[0] = I2CMasterDataGet(I2C2_BASE);

            uint8_t ui8Counter;
            for(ui8Counter = 1; ui8Counter < (ui8NumBytes - 1); ui8Counter++) {

                // initiate send of data from the MCU
                I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);

                // wait until MCU is done transferring.
                while(I2CMasterBusy(I2C2_BASE));

                // return data pulled from the specified register
                pReceiveData[ui8Counter] = I2CMasterDataGet(I2C2_BASE);

            }

            // initiate send of data from the MCU
            I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

            // wait until MCU is done transferring.
            while(I2CMasterBusy(I2C2_BASE));

            // return data pulled from the specified register
            pReceiveData[ui8Counter] = I2CMasterDataGet(I2C2_BASE);
        }
    }

    'Read answeing data' would be the data sequence i2c sends to initiate read? But I am not sure how I would send it.

    Best Regards,
    Can

  • Hello,

    Arrived here (forum) @ 06:00 - now nearing 09:00 - and our investors 'expect/demand' (some) 'Profit Seeking' enterprise.    (beyond my 'work-release' time/effort - invested here)

    Again - the 'sensitivity' of the 'MCU to Sensor'  "Data Read/Answer Back" - to my group's mind - deserves (your) further probing.    Is it not possible - maybe 'likely' - that a 'Failed Data Read/Answer Back' has 'latched the sensor's interrupt?    KISS argues for the 'Systematic Elimination' of 'likely issues' (i.e. Limit the Size/Scope of your 'battle-field') - the intense use of 'Test/Verify' - one item at a time - to (slowly, cautiously, logically)  build to a 'Final & Complete Solution.'

    The code sequence you presented likely will benefit from your 'Line by Line'  "Deep Dive: Examination" - as you attempt to 'tease out'  real meaning!    Indeed - as earlier was noted - such 'pre-written code' (sometimes) proves 'Effort-Lite & Speedy' - but (drastically) REDUCES USER COMPREHENSION!     Your commitment to (now) really analyzing such code - will serve you, 'Long into the Future' - even beyond 'SENSOR WARS' - and that's extremely beneficial to you/others - is it not?

  • Hi Can,

       The Accel datasheet says that the INTx is an OR gate of the various interrupt sources. See below. 

    It is also evident from you capture that the interrupt is not cleared because 1) not "all" data (13 bytes) are read or 2) data was not read successfully. You must have at least one of the registers or data not read successfully to have interrupt INTx remain active.

    If you don't have a logic analyzer than can decode I2C bus transaction, you will need to manually decode it either using either logic analyzer or the oscilloscope. 

      

  • Greetings Charles,      (and possibly other ... 'hanger's on' - who just may suffer the 'same disease' - as those (hapless few) here...)

    As the 'dead/dying' horse appears 'vendor sanctioned' for 'further beating' - let that abuse continue...     (I did try to provide an 'exit strategy' for the vendor.)

    Now my firm & I have an 'advantage here' (Numbers - today we are 6 strong) and 'gifted/motivated/focused young minds' are endlessly capable!

    Post above - vendor's Charles presented the 'Interrupt Controller's' block diagram - which is (somewhat) helpful.    Charles added, "INTx is an OR gate of the various interrupt sources."     Yet it remains (painfully) 'unanswered - even unexplored' (till now) ... which among the various interrupt sources must be examined?    (as that (unidentified) source - either 'in concert' - or alone - generated the interrupt!)

    Now our group finds (and believes) that the NXP Sensor Datasheet 'Woefully FAILS' in the full & proper disclosure & description of the Sensor Interrupt.     However w/'a 6 mind focus' - we believe we are the first here to uncover:

    14.1.12    Ctl_Reg 5

    "All interrupt signals routed to either INT1 or INT2 are logically OR’d together as illustrated in Figure 11, thus one or more functional blocks can assert an interrupt pin simultaneously; therefore a host application responding to an interrupt should read the INT_SOURCE register to determine the source(s) of the interrupt(s)."    

    That's both powerful and new info - is it not?    Has the poster's software known this - and properly executed the 'read of the appropriate source register?'    

    Digging a bit deeper...   (i.e. 'teasing out more detail' ... from among 116 pages)

    14.1.6 INT_SOURCE  register (address 0x0C)

    Interrupt source register.    The bits that are set (logic ‘1’) indicate which function has asserted its interrupt and conversely bits that are cleared (logic ‘0’) indicate which function has not asserted its interrupt. Additional interrupt flags for magnetic interrupt events are located in the M_INT_SRC register (0x5E).

    Reading the INT_SOURCE register does not clear any interrupt status bits (except for src_a_vecm, see Table 29); the  respective interrupt flag bits are reset by reading the appropriate source register for the function that generated the interrupt.     Where - till now - has this 'key finding' appeared?

    Staff & I continue to believe that the dominant 'entanglement' herein - is not the Vendor's MCU - but instead - the 'Too brief & vague' Description of the Care/Handling/and overall Management of the Accel Sensor's (pardon) 'Mystery Interrupt(s)' by (both) NXP & the 'follow-on' Accel-Board producer!

  • Great analysis cb1 team. Down to the bones of this device's intrincacies and modes of INTs handling. I would expect NXP to have published a detailed flow-chart diagram of all these inter-INT-relations and also a naked C piece of source  with some examples, where all that functionality would have been exposed with clarity. Though never is to late. John.

  • Thank you, John and speaking of 'too late' - staff notes that 'Check #2' will dispatch early next morn.

    We may conclude that the early (possibly the first 'read') should be of the Sensor's 'Source Register' - and gleaned from that - reads of (even)  multiple 'other Sensor Registers' - may be (or are likely) required!  

    It is believed that a 'Single Interrupt Source' (may) be properly cleared by a (pardon) 'fortuitous read' of the 'proper, interrupt generating, Register.'      Yet when the more complex (multi-sourced) interrupt arrives - the (simple) 'Interrupt clearing'  vanishes - and is replaced by a,  'Cascade of 'Multi-Register Addressings & Clears.'

    Again - this proves 'outside normal MCU responsibility' - and Sensor Maker & Board Producer - bear the bulk of 'Failed Disclosure'...

    'KISS' dictates that, 'Only after the Sensor is 'exhaustively understood & mastered' - should the MCU & its programming - come into focus.    None here - but for the original poster - should have had to 'Deep Dive' into the Accel Sensor - and (pardon) a forum 'weakness' has notably now been exposed.      To staff's & my mind - this is an MCU-Centric forum - and external devices must be fully understood & mastered by poster's (prior to presentation here) - to insure that all issues 'center' upon the MCU & its programming.

    Incorrect 'Targeting of an issue's (real) cause' - is responsible for 'misspent:  'Time, Cost & Effort' - and is to be avoided...

  • Hello cb1;

    At the bottom of table 30 it says

    "The src_drdy interrupt flag is cleared by reading out the acceleration data in accelerometer only mode and by reading out the magnetic data in magnetometer only or hybrid modes. In hybrid mode and with M_CTRL_REG2[hyb_autoinc_mode] = 1, all of the sensor data can be read out in a 12-byte burst read starting at register 0x01 (OUT_X_MSB)"

    // data ready interrupt is routed to pin 2
    ui8Register[0] = 0x00;
    I2CAGSend(ui32WorkerAddress, AG_CTRL_REG5, ui8Register, sizeof(ui8Register));


    This is where in my code, I route the data_ready interrupt to interrupt pin 2. all the other interrupts are orred then sent to pin 1.

    For now, I am using the accelmag interrupt only, then reading both accelmag, and gyro data. I made a small pcb that houses the sensor and the mcu,
    and sent it to the board house, and until it gets back in the mail, I will take a rest. (I have included few test points in the PCB)

    Although I could not get it perfectly synched, this sensor board makes the life of regular ROS user really easy.

    I have uploaded the source code and a little documentation on using it at github.com/altineller/fximu and included the python scripts for bridging the data,
    parameter passing, calibration, etc.

    Also here is a video from the rviz screen:  vimeo.com/359663238 (watch it at 720p :)

    Best regards, and thanks to all of you for your insights.

    -Can


  • Hello back, Can,

    can altineller said:
    "The src_drdy interrupt flag is cleared by reading out the acceleration data in accelerometer only mode and by reading out the magnetic data in magnetometer only or hybrid modes. In hybrid mode and with M_CTRL_REG2[hyb_autoinc_mode] = 1, all of the sensor data can be read out in a 12-byte burst read starting at register 0x01 (OUT_X_MSB)"

    Pardon - but to what purpose - are you providing this?     Never did your screen cap reveal (even remotely) any such '12-byte burst read!'

    can altineller said:
    I route the data_ready interrupt to interrupt pin 2. all the other interrupts are orred then sent to pin 1.

    Again - to what purpose?     'Interrupt pin 1 does not connect to your MCU' - thus you'll be BLIND to any/all such interrupts!     I'm at a complete loss!

    can altineller said:
    For now, I am using the accelmag interrupt only,

    May it be asked, 'How you (positively) know this?'    Even if 'outside your intentions' - other interrupts (i.e. diagnostic) may be generated - and by your 'reluctance to read' the 'Interrupt Source Register' - you'd not be informed nor advised - and (even) unexpected - especially unexpected -  interrupts would hang...

    can altineller said:
    this sensor board makes the life of regular ROS user really easy.

    Let's hope so - such has not been the case for your 'Band of helpers' - long 'bivouacked' here!   (while providing (almost exclusively) Sensor Guidance!)

  • Hello,

    I did capture and decode i2c bus during failure. It took me a while to get pulseview going on ubuntu with all the decoding facilities.

    Here is zoom of a successful transaction:

    1F is the address of the accelmag sensor. In a successful transaction, address write is followed by a data write (0x00 being status) register, then an adress read, then 13 data reads.

    Here is a zoom of a failed transaction

    address write to 1f, followed by data write, as in the successful transaction but after that It continues with data write, instead of data read.

    Also the first data write in the successful transaction is followed by an ack and start repeat, but in the failing transaction, it is followed by a NACK.

    I also captured the fail few times, and and observed that: it is not always following the data write, it could fail looking just like the successful transaction, except the read data is FF all the time. Here is one example of it:

    A common patterns between different fails are as PE2 goes low, (the accelmag interrupt) the i2c clock makes a spike. (I put a black dot to where it is)

    Now I am suspecting:

    a. it is the wiring

    b.i am using i2c2 at PE4, and PE5. interrupt pin is also PE2. maybe i2c2 is getting confused, as this isr triggers?

    c. the sensor maybe causing this spike, and corrupting the structure.

    Edit: I changed PE2 for PA7, using PA7 for accelmag interrupt. It still makes the same failutre, i2c clock spike is visible as A7 going down.

    I consider this project finished, but I can not stop myself from investigating the problem.

    Best.

  • Staff (especially) and I, 'Applaud' (loudly) this terrific 'SENSOR' analysis.    Staff is searching for 'Pulseview' - to be operated under WIN7 and/or WIN10.

    You may note that we (earlier) noted the 'neatness' of your 'preformed' wire connectors - yet judged them as 'too long' - inviting the potential for illegal signal introduction(s)!

    Your current 'Screen-Cap' proves 'outstanding' - we 'wish' such could have arrived (20-30) posts sooner.     (you may consider such 'wish' - for your 'gathering of facts' for 'Future Issues.')

    can altineller said:
    Here is a zoom of a failed transaction address write to 1f, followed by data write, as in the successful transaction but after that It continues with data write, instead of data read.

    We very much like your description detail (above) yet should it not have mentioned the 'missed' ACK' - which occurred, 'Immediately after that first Data Write (0x00)' - during the (first) failed-byte I2C transaction.    Note that vendor's Charles had 'urged' your 'search' for such 'failed ACK.'     The issue - at least in this specific case - appears to be the 'glitch' impressed upon your 'SCL' pulse train - during the very first 'Data Write' - which is almost certain to have caused (at least contributed to) the missed ACK!

    Earlier I advised you - along w/'shortening your wire interconnects' to 'Relocate the SCL wire as 'FAR as possible' from the wire bunch!'     It would even prove worthwhile to employ a 'shielded cable' to reduce the possibility of (unwanted) signal coupling.   (ground just one side of that shielded cable)

    Now you made the observation,  "c. the sensor may be causing this spike, and corrupting the structure."    

    There are (predictable) causes of such glitch/spikes - follows several:

    • inadequate voltage or current at (either) the MCU or Sensor board.    (such must be 'measured' during operation (program running) Not at 'idle.')
    • inadequate 'common ground' joining: Power, MCU board, Sensor board
    • mismatch of voltage level between MCU & sensor board.   (we recall your mention of 'voltage translators' upon the sensor board - these warrant 'measured examination.')    
    • it is 'w/in the realm' that your 'Set-Up/Config' of the I2C module proves - in some way - sub-optimal.   (i.e. it (usually) works - but may be 'vulnerable' to 'disturbance!')

    What to do - now?

    • the glitch upon 'SCL' may be 'MCU or Sensor' originated
    • insertion of a resistor (say 2K2 or so) between 'Sensor Interrupt & MCU's SCL pin' will (likely) enable the detection of (which) end - caused the spike.   (the 'earliest & largest' spike observance - indicates the 'most likely' - offending source.
    • we are 'bothered' as to 'How & Why - even If' - that very first (illegal) 'Data Write' (0x1F) - which should have been an 'Address Read') was 'MCU or Sensor' CAUSED!

    We have 'methods/ideas' - but leave that last analysis (which end first corrupted the 'intended Address Read' to you.     (as we are informed/advised that  "You 'cannot stop yourself.")      Note that a 'reasonable hint' as to identifying that 'Corruption source' has been provided... (Address Read 'forced instead' into 'Data Write') 

    You  may applaud our 'newly arrived' (college student staff) - should you determine this (mostly their) analysis well thought, presented and of value...    (simply 'click' the ** LIKE ** button...)

  • Hello cb1 & Can.

    Can, are you using USBee AX Standard, Plus, or Pro? Which USBee hardware are you using?

    My final suggestion would be to power the boards from a battery source and check again. Use

    the USB connection only for debug/comms with the PC. Set jumpers on board accordingly.

    cb1, PulseView needs skorg libs to have been installed prior to it's use and I wonder what Osc or SigAnal or MixedSig device you are using. 

    John

  • Hello John,

    Thank you - always good to 'read you here' - although 'staff/I' prefer our (other) commo channel.    (as do you - as staff recalls)

    Now we have no 'familiarity' w/'skorg libs' - fear that the 'Learning Curve' may be high - and we'll likely seek (other - faster/easier) alternatives.    (unless you can convince us - otherwise - we (always) listen/consider - prior to 'concluding.')

    Back to poster's Failed Sensor - 

    • while we wanted poster to enjoy the 'thrill of victory' - he's (pardon) too slow in responding - AND we have Two Client Sales Calls scheduled - for today - 'Saturday'   (especially as it is Saturday - this is how we 'BEAT' competitors - often 10x - even 100x our size - yet 'under-focused & poorly motivated!)
    • we differ (slightly) w/your guidance - we'd prefer that the poster, 'Power both boards from an 'independent yet adequate source' - which may or may not be a 'battery.'     If he's relying on his Eval Board to power the Sensor Board - that's 'highly suspect.'    Especially (as & if) that eval board is PC - USB powered!     As you know, John - in such glitch situations - Power is always among the 'top suspects.'
    • earlier I noted that the interrupt pin(s) default to 'Push-Pull' and staff ran several brief experiments (they are beyond motivated) and identified the 'Sensor Board provider's of 'voltage translators' as a (strong) candidate for 'glitching'  - when such 'push-pull' signal toggles!    And (that) is exactly when - the 'glitch appears upon posters (otherwise) pristine SCL signal line.     (the interrupt's 

    Plz STANDBY.....

  • Somehow - we can 'No longer edit/write into the above posting.

    Our investigation suggests this as the (best & only) 'fix' for this 'Sensor Wars' issue:   (do try in this order)

    • add a series R (say 2K2 - 4K7) between Sensor Interrupt & MCU input.   (i.e. MCU's GPIO input)
    • change the offending "interrupt signal from 'Push-Pull' (again, it's default) to 'open drain' - and employ a pull-up R as the manual states
    • add a 100K R (or higher) Pull-Down R - upon the Sensor's side of the Sensor's SCL input.

    It is theorized (and nearly confirmed here) that the 'Imposition of the voltage translator' (upon the SCL line) has left the Sensor's 'SCL Input" unable to  benefit from the 'low impedance' which the (unblocked/untranslated) MCU's SCL output - (normally) well provides.     In such condition - the sensor's input is 'vulnerable to such glitches.'      (staff has confirmed such occurrence - without ANY access to poster's Sensor - via carefully designed (highly overlapping) experiments - here...)

  • Hello,

    I am using USBee AX PRO. It is most likely a clone.

    I did power the eval board from a usb power bank, and made sure that laptop was plugged out from main source.

    I also setup usbee to 24mhz this time, and captured the same results.

    Now capturing at 24mhz, some of the fails do not feature NACK, but there is always this clock spike, as one of the interrupts is falling.

    Should I also try a plain old battery to power the eval board, or a usb power bank is noiseless enough? I also checked the signal lines with analog scope, and there is no sign of grounding misconfiguration.

    Best Regards,

    C.