|
|
View previous topic :: View next topic |
Author |
Message |
allenhuffman
Joined: 17 Jun 2019 Posts: 563 Location: Des Moines, Iowa, USA
|
rom * in sub-structure can cause function to not be resolved |
Posted: Wed Feb 05, 2020 11:33 am |
|
|
I already submitted this to CCS, but I wanted to post it here in case anyone else has stumbled on this.
PIC24 CCS compiler, multi-unit compile:
We ran into another issue with structures today, where a function reported:
Code: | *** Error 112 "main.c" Line 21(1,1): Function used but not defined: ... MakeButton 1087 SCR=4431 |
We narrowed it down to a "rom int8 *ptr;" in a sub-structure that was being returned by the function. Here is a sample.
button.h
Code: | #ifndef BUTTON_H
#define BUTTON_H
#include <main.h>
#include <stdint.h>
typedef struct
{
rom int8 *Icon_Ptr; // Comment this out, and it works.
int dummy;
} Basic_Button_Type;
typedef struct
{
uint16_t Button_Number;
Basic_Button_Type Basic_Button;
} Screen_Button_Type;
// PROTOTYPE
Screen_Button_Type MakeButton(unsigned int index);
#endif
|
button.c
Code: | #include <main.h>
#include "button.h"
Screen_Button_Type MakeButton(unsigned int index)
{
Screen_Button_Type tempButton;
tempButton.Button_Number = index;
//tempButton.Basic_Button.Icon_Ptr = 0x1234;
return tempButton;
}
|
main.c
Code: | #include <main.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "button.h"
#define NUM_BUTTONS 100
//Button_Type Buttons[NUM_BUTTONS];
void main()
{
Screen_Button_Type Buttons[NUM_BUTTONS];
for (int idx=0; idx<NUM_BUTTONS; idx++)
{
Buttons[idx] = MakeButton (idx);
}
for (int idx=0; idx<NUM_BUTTONS; idx++)
{
printf ("Button %u - Number:%u\r\n",
idx,
Buttons[idx].Button_Number);
}
while(TRUE);
}
|
When we build this, it reports MakeButton() isn't there. If we comment out the "rom int8 *Icon_Ptr;" line in the buttons.h header file, the function is magically available.
Our real project was actually using a function in other files, just fine, but in main.c or another .c file that function would not resolve.
We just moved the "rom" thing into the top structure and everything is fine, though we hope to have a fix so we can put it back where we wanted it. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Wed Feb 05, 2020 12:34 pm |
|
|
I've never heard of 'perfect programs' when using "multi-unit compile: ".
Historically the compiler has been a 'one pass - one program' type environment.
Every once in awhile, we see postings of 'odd' or 'strange' behaviour and someone usually figures it relates to attemping MCU.
I've never given it much thought since PCM v2.540 and PIC16C84s. |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 563 Location: Des Moines, Iowa, USA
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Thu Feb 06, 2020 4:17 am |
|
|
I think this again ties into function overloading.
ROM pointers are actually a very complex construction. I'm not at all
surprised that these can't be exported between compilation units. Perhaps
this should be a documented restriction. Problem is that these rely on
a table built as part of the compile for resolution. Since this won't be
passed with import/export, result, problem....
What's happening is that the structure declaration is being 'simplified'
to remove this when exported. This results in the function no longer actually
'matching' it's declaration, so the imported version does not give the
physical definition for the function. So the message.
I think it really is worth saying that CCS is fundamentally a single pass
compiler. The support for MCU's, has always been limited, and it is far
better not to use it. A very large percentage of the problems are when
people insist on using CCS with MCU's. |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 563 Location: Des Moines, Iowa, USA
|
|
Posted: Thu Feb 06, 2020 8:41 am |
|
|
There's a related issue we found, and I went and created overload functions for a half dozen types (structure, int, char *, float, double, etc.) and ran some tests on that. I found another issue where, since you can't overload a (void) function, as soon as you have one, it won't be resolved if you have a prototype for it. Removing the prototype allowed it to work.
As we may migrate to another architecture down the line, I am trying to make all new code modular and portable. Which is often not possible here _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1355
|
|
Posted: Thu Feb 06, 2020 7:36 pm |
|
|
allenhuffman wrote: |
As we may migrate to another architecture down the line, I am trying to make all new code modular and portable. Which is often not possible here |
Modular is doable. We have tons of modular code here. Portable is a bit open ended. CCS C is a K&R version 1 variant, so if you want it portable to an ANSI compiler, then you probably won't get there easily. They are effectively very different languages. ANSI C has a lot more semantics defined than K&R, which is very open ended.
CCS C is very portable among different PIC chips, which is the target they are aiming for. Note that using multiple compilation units is not a requirement for modularity or portability, so I agree with Ttelmah that one should stick to single file compilation for a single pass compiler. At least until they work out all the kinks in multiple file compilation.
If you want portability, I would recommend using a top down method rather than bottom up. Doing this I have been easily able to move code I made in CCS to an 8051 microcontroller, a cortex M0+ arm, a cortex M4, and a Jetson TX2 without hardly any changes, just the low level peripheral functionality at the bottom of my design. In addition, I have been able to simply replace C files in order to completely change drivers to external interfaces (like switch to a SPI interface chip from an I2C chip for example) with no change to my business logic. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Fri Feb 07, 2020 3:15 am |
|
|
Totally.
I use the same libraries on projects here on Raspberry Pi, Arduino, and
PIC. However it is vital to actually understand the differences in meanings
that some things have. ROM * in the first two, does not actually result
in things stored in ROM. In ANSI C, ROM * is just a signal to say that the
RAM values cannot be changed. In CCS C it instead means a value actually
'held' in ROM. Given the different memory architectures, this is a very
important difference. It is historical. CCS actually started to use 'ROM' as a
keyword before it was introduced in ANSI C. The equivalent to ROM in
the Arduino, is PROGMEM.
Write using original K&R syntax. Don't try to use later constructs. Then
when using anything like ROM *, only use this when you actually want to
produce the real effect of storage in ROM, and change this to match the
processor you are using. 'Portability' requires you to understand the
different processor architectures and code for them. Code for a Harvard
architecture is always going to be different to that for Von-Neumann
architecture and you need to understand the abilities and limitations
as you write. |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 563 Location: Des Moines, Iowa, USA
|
|
Posted: Fri Feb 07, 2020 10:22 am |
|
|
For anyone interested, CCS has an official document about their ANSI compliance, and notes areas where they aren't.
http://www.ccsinfo.com/downloads/ansi_compliance.pdf
The Microware Ultra-C compiler for OS-9 was similar. While it was a fairly-strict ANSI-C compiler, there were some things that could not be done due to OS-9 using position-independent re-entrant code (I forget what, but I know something about "const" there was handled differently). _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1355
|
|
Posted: Fri Feb 07, 2020 11:31 am |
|
|
Keep in mind that they update the checklist. It isn't fully vetted by the ISO standards committee. It's often times wrong as well. I've sent multiple reports about non compliance. They fixed some but still haven't fixed all (though they are working on it).
The ANSI C standard defines a lot of "abstract machine" semantics that aren't on that checklist and that they don't support.
For example, Duff's Device was vetted by the ANSI committee as standard based on the semantics as defined in the ANSI standard. However, CCS supports K&R semantics (which are largely open and not defined), so it cannot compile the ANSI version of Duff's Device:
Code: |
void main()
{
short *to, *from;
int count;
int n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
}
|
which happily compiles in GCC but CCS doesn't understand because it doesn't implement ANSI control structure semantics as defined in the standard.
NOTE: if you are wondering the use of the example, it's useful in various types of optimizations on specific processors and is the foundation to protothreads (I implemented them in CCS C, but had to use a different method with compiler extensions).
NOTE: Sorry if this sounds like I am disagreeing with you. Not my intention. My hope is that you just keep it in mind when you are designing for portability. And I hope you keep submitting the bugs you find to CCS via their support email. The more that can get fixed, the better. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Fri Feb 07, 2020 1:41 pm |
|
|
I actually asked if they could change their syntax support to allow
this to work some time ago. Perhaps I need to remind them of this!... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|