Jump to content
 
  • 0
Sign in to follow this  
Orunmila

I used to use @ to locate variables but since XC8 2.0 this is no longer working?

Question

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'

Share this post


Link to post
Share on other sites

1 answer to this question

Recommended Posts

  • 0

I came across this and thought I would post it here in case others hit the same snag.

In the past it was possible to hard locate a variable using XC8 like this :

 volatile unsigned char   TMR0    @ 0x01;

Although this was convenient it was also not strictly acceptable C syntax, so if you were using a linter on your code to check if you have anything untoward in there it could flag this as being incorrect C syntax.

In XC8 v2.0 the syntax was switched to what Microchip calls the CCI (Common Compiler Interface) syntax, which uses the following syntax to hard locate a variable.

volatile unsigned char TMR0 __at(0x01);

Since this has a double underscore and the brackets it is more compliant to the C standards.

With XC8 2.0 it is possible to compile your old code using the @ syntax if you set the compiler settings to use "C90" format. The setting looks like this, it is under "XC8 Global Options" and is called "C standard".

image.thumb.png.04bfa623f83cea75176057a07e200f63.png

 

If you want to use something which does not use a compiler specific extension such as @ or __at() you can always do it like this:

// This defines the TMR0 register - volatile is important to tell the compiler that this is a volatile register, 
// read more about volatile in the XC8 Users Guide
#define TMR0 (*(volatile uint8_t*)0x0001u)  
  
// You can now access it like normal, something like this.
TMR0 = 0x12;

Hope that helps 🙂

There are a couple of other CCI keywords which are described in the compiler user's guide such as __interrupt which you can also get to work by switching back to the pre 2.0 syntax by choosing "C90" as shown above.

I also posted about this on the Microchip forum on this thread. Below is a copy of that post.

8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----

Hi Guys here is the full story:


With XC8 2.0 we are very excited that we get an improved compiler front-end, which brings things like C99features to us which we are very happy to have.
 
Unfortunately pre-XC8 2.0 we had some keywords in the compiler which were not strictly conforming to the C standard. 
 
Keywords like these:

  1. Using "bit" as a variable type
  2. Using "interrupt" to mark interrupt functions
  3. Using "int i @0x88" to hard locate a variable at a ram location
  4. Using "#asm" to create inline assembly.

Together with the wonders we get with the new front-end we have also lost support for the "old" way of doing these things which was not strictly standards compliant. XC8 has for a while allowed the corrected syntax but with 2.0, due to the improved front-end implementation, these non-standard keywords are no longer available.
 
Unfortunately MCC has been using too many of this pre-XC8 2.0 syntax and this can now cause some compatibility issues.
 
To minimize problems the IDE will default any "old project" you open (and change the compiler to XC8 2.0) to pass in "C Standard = C90" which can be set under "XC8 Global Options". This will tell the compiler to use the pre-XC8v2.0  front-end to compile your code which should give you the same behavior you got before with XC8v1.45 and earlier. If you use MCC with this project you should experience no problems.
 
When you make a new project it will default to "=C99" which means the deprecated syntax will cause compilation errors where the above syntax was used. You can get these projects to work easily by either fixing the code to use the standards-compliant CCI syntax - or changing the define to C90 and leave the code unchanged (leaving the problem for later so to speak)
 
The correct syntax is (the underscores are all double-underscores btw.):

  1. "__bit" for the "bit" type
  2. "__interrupt()" instead of just "interrupt" - yes the brackets are required.
  3. To hard locate a variable use e.g. "int i __at(0x88)"
  4. For inline asm use "asm()"

There are also a couple of small issues which should be resolved in the next compiler release. These are:

  1. The int24_t type define in stdint.h is not present for C99 mode, it will be there soon.
  2. There is a change in the Vectored Interrupt vector names which we are still looking into, contact me if you run into this one and I can help.

We have released a new version of the MCC 8-bit libraries which will addresses these issues by converting the code to CCI compatible syntax which will make it work on all modes and versions of the XC8 compiler. This can be downloaded from microchip.com/mcc. 

The first version of the libraries with the update is v1.75 

 

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
Answer this question...

×   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.

Sign in to follow this  

 


  • 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 KM1
      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
         
    • 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.
       
×
×
  • Create New...