7 Replies Latest reply on Nov 11, 2019 12:37 PM by TeMa_1467596

    Corrupted uint16 variable in a 4000  line main_cm0p.c file

    TeMa_1467596

      I have a 4050 line main_cm0p.c file in PSoC Creator using GCC 5.4-2016-q2-update compiler.  It's been working fine but I now have a uint16 variable that is a counter that's only used within main_cm0p.c to keep track of the next free memory slot (there are 1000 slots in my system).  The variable is defined...

       

      uint16 nextFreeFFslotNumber = 0;

       

      at the top of my file and then it's set in a function called by main and I've printed the value out over UART after it's set and it is fine.  At some point when an event happens, I use it to generate a load of addresses and then I increment it like this...

       

      dirRecord.slotRef = nextFreeFFslotNumber++;

       

      but the value that was ending up in slotRef is wildly wrong, like 2570 (always the same number) when it should be 3 or 4.  I've tried printing nextFreeFFslotNumber at several places and found out that it gets corrupted before it even gets to the line of code above (that line does increment it from 2570 to 2571) and there are no other places that the value is set!!!!

       

      I tried making the declaration volatile (and static) but the problem is the same.  I tried taking out the optimization and changing the optimization level for the cm0 but it's still broken.  Now I'm thinking that there's another variable that's corrupting this one.  Any ideas or suggestions how to debug this?  How do I get to look at the .map file to see what's before it?

        • 1. Re: Corrupted uint16 variable in a 4000  line main_cm0p.c file
          MoTa_728816

          Hi,

           

          This sounds like there is a memory overrun access by neighbor variable(s).

          Don't you have some array defined near the variable nextFreeFFslotNumber ?

           

          Something like

          =====

             char strArray[6] ;

             uint16 nextFreeFFslotNumber = 0

             int intArray[8] ;

          =====

           

          Then accessing strArray[6] or strArray[7] by such as

              sprintf(strArray, "%s", "a sting which is more than 5 letter long") ;

          or

             for (i = 0 i < 10 ; i++ ) { /* index 8 and 9 are overrun access */

                intArray[8] = i * 32 ;

            }

           

          Off my head, I'm not sure which (after or previously defined) variable is the problem,

          but accessing an array with exceeding its defined capacity often causes a symptom like what you wrote.

          So it's worth checking.

           

          moto

          1 of 1 people found this helpful
          • 2. Re: Corrupted uint16 variable in a 4000  line main_cm0p.c file
            TeMa_1467596

            Motoo San,

             

            Thanks for the suggestion - I had been looking for an array bounds overrun as the likely culprit and today I found exactly that. Then I came here to update my post and found your suggestion but thanks anyway for the input - in fact you were right so I'll give you the correct answer award!

             

            This has caught me out before so here's a question...  isn't there some way to make C tell you when you've addressed an array index outside the defined size?

            • 3. Re: Corrupted uint16 variable in a 4000  line main_cm0p.c file
              MoTa_728816

              Dear TeMa-san,

               

              Thank you very much for the correct answer mark!

               

              As far as I know of, I have not heard of C language support of Array Boundary checking.

              But if you run MISRA-C checking it will warn about possible array over run.

              IAR EWARM compiler has such feature, but I'm afraid that general GCC does not.

               

              Best Regards,

              11-Nov-2019

              Motoo Tanaka

              • 4. Re: Corrupted uint16 variable in a 4000  line main_cm0p.c file
                AchimE_41

                Hi,

                 

                You can add a data WatchPoint while debugging, so the code is stopped whenever your variable is written. Depending on optimisations code might stop few instructions away, but it should give you a hint where the error comes from.

                 

                 

                In case a known value is written to the variable, you could check for that value only by using following code:

                CoreDebug->DEMCR = CoreDebug_DEMCR_TRCENA_Msk  | /*enable tracing*/

                CoreDebug_DEMCR_MON_EN_Msk; /*enable debug interrupt*/

                 

                DWT->COMP0 = (int)&test_var; /* set pointer to test Variable */

                DWT->MASK0 = 0; /* N/A */

                DWT->FUNCTION0 = 0; /* N/A */

                 

                DWT->COMP1 = 9;     /* Value to test for */

                DWT->MASK1 = 0;     /* match all comparator bits, don't ignore any */

                DWT->FUNCTION1 =    (0b00 << 10) |  /* DATAVSIZE 00 - match byte */

                (1 << 12) |     /* Data Match compare value pointer in COMP1 */

                (1 << 8) |      /* DATAVMATCH Enable data comparation */

                  (0b0110 << 0);  /* generate a watchpoint event on write */

                 

                Kind regards,

                Achim

                1 of 1 people found this helpful
                • 5. Re: Corrupted uint16 variable in a 4000  line main_cm0p.c file
                  TeMa_1467596

                  Achim,

                   

                  That sounds useful.  Would it still interrupt if the write to the variable was caused by an out of bounds array?  Is it actually detecting a write to an address rather than a named variable?

                   

                  Ted

                  • 6. Re: Corrupted uint16 variable in a 4000  line main_cm0p.c file
                    AchimE_41

                    Yes it it watching an address and any write access and/or read based on your configuration is monitored and triggers the interrupt/breakpoint.

                    There is also the Mask register where you could watch a certain memory area instead of just a single address.

                     

                    Only thing I noticed is that if you are debugging it will force a breakpoint rather than causing an interrupt. If you run the program it will trigger the interrupt instead.

                     

                    It is an ARM core feature, so you should find some information on WatchPointer via google.

                    I don't know if we have any good KBA on it here at cypress.

                     

                    Achim

                    1 of 1 people found this helpful
                    • 7. Re: Corrupted uint16 variable in a 4000  line main_cm0p.c file
                      TeMa_1467596

                      Thanks, I looked it up, it's found under "WatchPoint".

                       

                      Ted