Jump to content
 
KM1

RTCOUNTER example - (solved) Caused by Silicon Errata

Recommended Posts

Hello,

I have run into a strange (for me) issue with the rtcounter module as provided by MCC and shown by the example program in the blog area of this site. I am using MPLabX and XC8, both up-to-date versions and I am trying the example on a pic18F47k40 xpress board. The issue is I set an output (RA4) in main after initializing the pic and then enter the while(1) loop where the rtcount_callNextCallback(); is called. The output now is turning on and off. The off duration is typically ~60u seconds, and on time can be varied with changes to the timer interrupt settings (I use a 1mS timer0 in 16 bit mode) and the number sent to the callback. Approximately every 3mS, the off time increases such that that cycle (only) is approx 50% duty cycle.

Turning the output on or off in the callback routine has no effect - I initially wanted to toggle on and off at a speed visible to the eye. Commenting out the callback in the main loop stops the output from going low.

I have checked errata and used the data sheet to confirm register settings, I tried moving the current-limited LED from RA4 to RA2, and I have studied the example program looking for obvious differences that may cause this behaviour.

I would appreciate thoughts and/or suggestions.

Keith
   

Share this post


Link to post
Share on other sites

Can you please post some code? Or even better the entire project (you can turn your project in to a zip file using the "Package" option when you right-click on the project name in MPLAB-X.)

I am not sure I understand the problem yet.

Share this post


Link to post
Share on other sites

The problem is the output is set high but goes low without a command saying to do so. I have zipped the project and have added it to the file download area

 

Share this post


Link to post
Share on other sites

Got it I am taking a look for you. BTW. You can also upload directly here by attaching to your post 🙂

 

 

Share this post


Link to post
Share on other sites

Oh my, I have run it in the simulator and this is definitely broken. Let me debug it and I will get back to you with a clear answer on how to fix this and what is going on.

EDIT: OK. RTCOUNTER is designed for the timer to represent the bottom bits of a concatenated timer value. This ONLY works if the timer runs from 0 and overflows at FFFF. This means that you cannot set the timer period to 1ms the way that you did there, you can ONLY set the timer period to MAXIMUM which means the timer will run from 0x0000 to 0xFFFF, forming the bottom 16 bits of the concatenated timer.

I cannot test the code with TMR0 in the simulator as the simulator has a bug which does not allow TMR0 to work in 16-bit mode, and I do not have a 47K40 on me to test it on the actual hardware 😞

What you should see is this:

1. TMR0L and TMR0H should count upwards from 0x0000. 
2. When you call create timer it should take the current value of (TMR0H << 8 + TMR0L) and add 1000 to this, that should give you something like 1222 the first cycle.
3. At this point every time you call rtcount_callNextCallback() it should compare the current timer value obtained by ReadTimer() to 1222, it should do nothing until the timer exceeds 1222, then it should call the callback once and add 1000 to the timer absoluteltimeout, which should now be 2222, and the cycle should repeat.

Please check if this is what you see on the hardware, we can fix the period when this is working correctly. This should have a period of 8ms per tick, so 1000 should go about 8 seconds ...

What happened in your case in 16-bit mode with the period set to 1ms is that the rtcount_callNextCallback() routine ALWAYS thought that there was a timeout as it sets the timeout to be at something like 222, but because you reload the timer with a value much larger than this the routine always thinks the timer has timed out and it toggles the i/o pin on every pass through the while(1)

Share this post


Link to post
Share on other sites

To confirm above I changed your code to use TMR0 in 8-bit mode so that I can test it in the simulator. With the prescaler I set the period to 1.024ms, so it is not quite perfect, but close enough for a test (2.4% error).

I attach the project with these settings, this works fine in the simulator.

xpress1.zip

Share this post


Link to post
Share on other sites
Quote

scope.jpg

Ok now I am quite stumped. Is the time period there around 1ms per pulse?

Is it possible for you to single step (instruction step) the code in the debugger and see when the line toggles?

 

Share this post


Link to post
Share on other sites

Hi,

I am seeing the issue if  " rtcount_callNextCallback();" is called in While loop.

while (1)
    {
        // Add your application code
       //IO_RA1_SetLow();
        // Check if the next timer has expired, call its callback from here if it did
        rtcount_callNextCallback();
    }

I tested through debugger as well and see that after 5 round inside " rtcount_callNextCallback();" it Resets.

I wanted to attach the RA4 output signal but I am not able to figure it out how.

By default Stack Overflow is enabled,

#pragma config STVREN = ON    // Stack Full/Underflow Reset Enable bit->Stack full/underflow will cause Reset

If I disable it then RA4 output is "Low". I am not able to pinpoint to the exact line which is causing the issue. however, I will continue on this and update. 

 

 

 

Share this post


Link to post
Share on other sites

Hey Prasad, that should use almost no stack space? Very strange. Can you check the reset bits to see if it really is a stack overflow?

 

 

Share this post


Link to post
Share on other sites
30 minutes ago, Orunmila said:

Hey Prasad, that should use almost no stack space? Very strange. Can you check the reset bits to see if it really is a stack overflow?

 

 

I checked the "PCON0" register There was no Stack Over/Underflow but the "nRMLR" bit was low which means MCLR Reset. Default value as per datasheet should be PCON0 = 0011110x, the obtained value was 0011010x (STKOVF  STKUNF  WDTWV RWDT  RMCLR  RI  POR  BOR)

Even with STVEN enabled if we comment " rtcount_callNextCallback();"  device doesn't Reset.  We need to test " rtcount_callNextCallback();" function completely.

 

Share this post


Link to post
Share on other sites

Hi KM1,

If we load RTCOUNTER is loads the "Timer0 without interrupt" but, i see that the interrupt is enabled in the code. 

Could you please give some details on why Interrupt is enabled.

Also, I see EUSART and SPI-MASTER code in it if you share some details on this then it may be helpful.

  • Like 1

Share this post


Link to post
Share on other sites

Hmmm, that is very interesting. If it resets on the hardware due to a MCLR reset, and not in the simulator it is probably nothing to do with the software!

Share this post


Link to post
Share on other sites
11 hours ago, Prasad said:

Hi KM1,

If we load RTCOUNTER is loads the "Timer0 without interrupt" but, i see that the interrupt is enabled in the code. 

Could you please give some details on why Interrupt is enabled.

Also, I see EUSART and SPI-MASTER code in it if you share some details on this then it may be helpful.

I enabled the timer0 interrupt because it appeared to be a requirement to run the rtcount example. I don't understand how the callback would use the interrupt routine without my enabling the interrupts?

The eusart is to be used for debugging and the spi code is to allow the use of an ethernet interface module which is the primary goal for this project. I have not done anything with either as I was testing the rtcount module first. I very much like the approach used in the recount example.

Keith

Share this post


Link to post
Share on other sites

Best guess right now is that you are hitting this Silicon bug. Please see if you can attempt this workaround. 
 

image.png

Share this post


Link to post
Share on other sites

The full errata can be downloaded here : http://ww1.microchip.com/downloads/en/DeviceDoc/PIC18F27-47K40-Silicon-Errata-and-Data-Sheet-Clarification-80000713E.pdf

If this is the problem then this is quite a serious problem as everyone using C with those boards will be caught by this! It would mean that they ran a production batch of those boards with rev A2 silicon!

C

Share this post


Link to post
Share on other sites
I narrow down the issue. The controller is restarting due to "Stack Overflow".
 
line number 220 code is causing the issue,
      reschedule = timer->callbackPtr(timer->payload);
 
It looks like its a recursive which causing the issue but, I was not able to understand the part of the code how it works in a given time.
 
We tried by adding "NULL" pointer check to that line that worked but, I feel like as an application or function of API it may not but, it just saves from restarting the controller.
       if(timer->callbackPtr != NULL)
                reschedule = timer->callbackPtr(timer->payload);
 
I have attached the snapshot of the StackOverflow Flag setting.  
 
BTW. looks like its a simulator bug on showing nMLCR bit has low every time. I tested the voltage on the nMLCR it's not low nor dropping while executing the program.

line220 causing StackOV.jpg

  • Helpful 1

Share this post


Link to post
Share on other sites

Thank you  both for your very helpful suggestions and the time you are putting in to sort out this issue. I will be out of the office today and tomorrow, but will have time at the end of the week to do some more investigating at my end.

Keith

Share this post


Link to post
Share on other sites

@Prasad, that pointer cannot be null according to the C code, it is initialized at startup. I think you just found the problem! Good detective work!

Of course if you check for null there and it is indeed null then the device will not reset but also the callback will never be called so the problem is not yet solved...

Let’s try out that errata, I think that will fix it. If not let’s keep investigating how it is possible for this pointer to be null. It is either not initialized (the errata could cause this) or it is overwritten woth null at some point. Which one is it?

 

Share this post


Link to post
Share on other sites
4 hours ago, ric said:

You don't need to edit powerup.as if you tell the compiler about the " NVMREG" errata.

https://www.microchip.com/forums/m969418.aspx

 

 

Oh wow I did not realize this was implemented as an errata! That would by far be the best option! I am going to try it out and upload the project here, then KM1 should be able to test when he gets back!

 

Share this post


Link to post
Share on other sites

Here you go - I have compiled this with the +NVMREG option, and confirmed that this writes the appropriate bits before doing initialization of the function pointers through the TBLRD instruction.

KM1, I will leave this here for you to test. Uploading the project zip as well as the HEX I compiled.

I did find a host of bugs in the RTCOUNTER when you are using TIMER0 in 8-bit mode! It is clear this combination needs some work. 

1. The left shift in readTimer was still <<16 even if the timer was 8-bit causing all kinds of havoc
2. The definition of the global variable g_rtcounterH was 16-bit limiting us to 24bit range, but RTCOUNTER_CONCATENATE_TIMER_TICKS was defined specifying a 16-bit range so the math was all wonky

I set the timer to have a tick of 1us which makes the math easy, and then got 1s by setting the timer reschedule value to 1,000,000, which should make the output toggle every 1s, or come on every 2s ...

For the blog post we used TIMER1 and for that implementation everything seemed to be correct.

Also I did not run it long enough to rebase (wrap) so that may also have issues, that should happen after 4000 seconds, which is longer than it sounds ...

 

 

xpress1.zip

Share this post


Link to post
Share on other sites

Hi KM1/Orunmila,

adding "NVMREG"  even I am able to see the proper result on hardware.

 

RA4_Signal.jpg

errata_Correction.jpg

Xpress_project_debugMode.jpg

  • Helpful 1

Share this post


Link to post
Share on other sites

Good job tracking this down folks.  It sounds like the templates need a little help for the 8-bit case and probably for the 32-bit case (running this on a PIC32).  Is there any news on getting the templates on a public repository (GITHUB) so we can contribute fixes and help out?

  • Haha 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


 


  • Popular Contributors

    Nobody has received reputation this week.

  • Similar Content

    • By Orunmila
      error: variable has incomplete type 'void'
      If you are getting this error message trying to compile code that used to work or from some example code you found somewhere it is very likely because of the changes in the XC8 interrupt syntax introduced with V2.0 of XC8.
      Specifically I am getting this today for my interrupt service routine definition. I used to use the age-old way of doing this in XC8 as follows:
      // Old way to do this void interrupt myISR(void) { // Old way Interrupt code here } After the changes to the XC8 compiler which were mostly motivated to get better C standard compliance, particularly with C99, the syntax for that function should now use the commonly adopted concept of function declaration-specifier attributes, which traditionally start with 2 underscores and contains either a list of parameters in brackets or have empty brackets if no parameters are present. 
      // New and improved and C99 compliant way to specify an interrupt service routine in XC8 void __interrupt() myISR(void) { // New and improved interrupt code here } This syntax is now also consistent between XC8, XC16 and XC32
      Please see this post for more information on how to either work around this or change to the new syntax.
      https://www.microforum.cc/topic/5-i-used-to-use-to-locate-variables-but-since-xc8-20-this-is-no-longer-working/
    • By Orunmila
      I just downloaded XC32 V2.15, I was using V2.10 before. I find that some of my projects no longer compile. On my first check I noticed that the problems seem to occur when inline functions are used and the same header where the inline implementation is done is included in more than one compilation unit?
      Has any of you seen similar issues?
      I will investigate further and post here if I arrive at an answer.
       
      UPDATE: Ok, I managed to make a small test project to replicate the problem. I am attaching it here. 
      TestInlineXC32_2.15.zip
       
      Next I am going to test this on some other compilers to see what the deal is. I have confirmed that with that project when you switch it to V2.10 or older it all compiles just fine, but if you use V2.15 it failes to link with the following error:
      "/Applications/microchip/xc32/v2.15/bin/xc32-gcc"   -mprocessor=32MZ2048EFM100  -o dist/default/production/TestInlineXC32_2.15.X.production.elf build/default/production/main.o build/default/production/otherFile.o          -DXPRJ_default=default  -legacy-libc    -Wl,--defsym=__MPLAB_BUILD=1,--no-code-in-dinit,--no-dinit-in-serial-mem,-Map="dist/default/production/TestInlineXC32_2.15.X.production.map",--memorysummary,dist/default/production/memoryfile.xml
      nbproject/Makefile-default.mk:151: recipe for target 'dist/default/production/TestInlineXC32_2.15.X.production.hex' failed
      make[2]: Leaving directory '/Users/ejacobus/MPLABXProjects/TestInlineXC32_2.15.X'
      nbproject/Makefile-default.mk:90: recipe for target '.build-conf' failed
      make[1]: Leaving directory '/Users/ejacobus/MPLABXProjects/TestInlineXC32_2.15.X'
      nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed
      build/default/production/otherFile.o: In function `myInlineFunction':
      /Users/ejacobus/MPLABXProjects/TestInlineXC32_2.15.X/inlinedheader.h:6: multiple definition of `myInlineFunction'
      build/default/production/main.o:/Users/ejacobus/MPLABXProjects/TestInlineXC32_2.15.X/inlinedheader.h:6: first defined here
      /Applications/microchip/xc32/v2.15/bin/bin/gcc/pic32mx/4.8.3/../../../../bin/pic32m-ld: Link terminated due to previous error(s).
      collect2: error: ld returned 255 exit status
      make[2]: *** [dist/default/production/TestInlineXC32_2.15.X.production.hex] Error 255
      make[1]: *** [.build-conf] Error 2
      make: *** [.build-impl] Error 2
      BUILD FAILED (exit value 2, total time: 680ms)
       
       
       
    • By Orunmila
      If you have purchased a "MPLAB(R) Xpress PIC18F47K40 Evaluation Board" from Microchip (part number DM182027) and you are running into difficulty because the board is behaving strangely it is most likely caused by a silicon errata on this device!
      The errata can be downloaded here: http://ww1.microchip.com/downloads/en/DeviceDoc/PIC18F27-47K40-Silicon-Errata-and-Data-Sheet-Clarification-80000713E.pdf
      The relevant section of the Errata is shown at the end.
      What is happening is that the compiler is using a TBLRD instruction somewhere and this instruction is not behaving as expected due to a silicon bug in REV A2 of the PIC18F47K40, causing the read to fail and the program to malfunction. Typically this happens as part of the C initialization code generated by the XC8 compiler, and since the compiler is optimizing, changing the code may cause the problem to temporarily disappear because you have few enough global variables that a table read is no longer the fastest way to initialize the memory segment for variables with static linkage.
      The XC8 compiler can avoid generating the sequence which will cause the failure if you tell it in the linker settings to implement the workaround for this Errata. This is done by adding +NVMREG to the setting as follows. Note that this is under the section "XC8 Linker" and the Option Category "Additional Options".
       

       
      This is the relevant section of the Errata.

       
       
    • By Orunmila
      I have a bunch of old projects using the @ method to hard locate variables at a specific location in data memory, but since I upgraded to XC8 2.0 none of these are working any more!
      How do I do this with the latest compiler? I am using XC8 v2.xx.
      I also saw this error at my interrupt service routine and I suspect that this is the same problem.
      My interrupt code looks like this 
      void interrupt my_isr(void) { ... my code here } error: variable has incomplete type 'void'
    • By Orunmila
      I think this is probably the most common question we get from beginners. Everybody gets confused with LATx and PORTx and run into Read-Modify-Write issues, so how does this really work?
       
    • By Orunmila
      I have a fairly general question for you all. I keep on running into situations where I need to mix C and ASM. Sometimes this works out easily by just using some asm("") instructions in the middle of my function, but sometimes I really feel like I could benefit from writing a function in ASM and calling it from C.

      I think my best example of this is the implementation of cryptographic functions such as AES or SHA. For these I see sometimes a 2x or even 3x speed improvement over what the compiler produces and I need to use these from more than one place so I really need a C function I can call to do these but I reallly need to implement it in ASM.
      Whenever I ask about mixing C and ASM I am told just not to do it, but it still seems to me that there are a lot of situations where this really is the best way to go?
      I recall a converstation with @holdmybeer where he needed very precise timing and the optimizer would always change the timing depending how the banks ended up being laid out (adding or removing bank switches), where implementing a function in ASM also seemed to be the solution.

      So I would like to get some opinions on this, do you guys agree? Any thoughts on this?

      PS. We recently had a related discussion about calculating parity as another example.
       
    • By Orunmila
      This zip file contains the project implementing Duff's Device using XC8 and a PIC16F18875 which goes with the Duff's Device Blog. The project can be run entirely in the simulator in MPLAB-X so no need to have the device to play with the code!
      See the blog for more details
       
×
×
  • Create New...