Jump to content
Sign in to follow this  
davidb

Rom Data Type In A Function

Recommended Posts

Hi,

 

I am currently working on some code that is used in a number of similar equipments. These have different 16-bit lookup tables (arrays) in RAM and so I use conditional directives for the different equipments so that the unused arrays get removed.

 

Because of the array size, no real need for speed and plenty of flash memory I decided to move them into flash using 'rom' lookup tables. For convenience I defined and initialised each 2 x 8-bit 'rom' table within separate functions together with the code to extract and return the 16-bit values. This made it easier to substitute the RAM array read with the ROM table read for testing.

 

In a way I felt that defining the 'rom' within the function might not be the right thing to do but it seemed to work O.K. However, I was slightly surprised to find that although the conditional compilation correctly removed the unused functions the the 'rom' tables inside them were left behind and therefore used more flash than I was expecting.

 

I would be interested to know if this effect is by design or just a side effect.

 

I can get round it without any problem but I thought that it might be useful information to anyone else trying to be clever!

 

SourceBoost C V7.11

PIC18F87K22

 

davidb

Share this post


Link to post
Share on other sites

davidb,

In a way I felt that defining the 'rom' within the function might not be the right thing to do but it seemed to work O.K. However, I was slightly surprised to find that although the conditional compilation correctly removed the unused functions the the 'rom' tables inside them were left behind and therefore used more flash than I was expecting.

 

I would be interested to know if this effect is by design or just a side effect.

It would be good if you could post a small program that demonstrates what you describe.

 

Regards

Dave

Share this post


Link to post
Share on other sites

Dave,

 

Basic project attached to demonstrate the problem.

 

Note that in this example the rom definitions in each function are the same but would normally be different and much larger in size. The unused rom read function is apparently removed so I would expect the associated rom definition to be removed as well. However both are still in program memory.

 

As I said it is not a major problem as I was just experimenting and happened to stumble upon this by accident. My full project now avoids these types of functions anyway

 

SourceBoost Rom Test.zip.

 

Regards

 

davidb

Share this post


Link to post
Share on other sites

Hi

 

As I see it you are missing a couple of #ifdefs in this code sample.

 

In fact, in "main", you don't call one of the functions "read_table1/2" depending on your initial #define.

But the code for both functions with its tables is still part of the program.

 

When you build this sample you may notice the message stating that the unused function as "unreferenced"

So it will depend on the level of optimization if the code for the unreferenced function is excluded or not.

 

Based in this sample, you have to use the conditional compilation in every part of the code that deals with the tables, in this sample it will mean surrondig the functions "read_table1/2" with "#ifdef", in a real project it may escalate to several "#ifdef" spread all around the code.

 

IMHO there is a far better way of dealing with this.

 

As you want to use "table1" or "table2" and never both you should simply have "table" and use the conditional compile to select wich set of values to use.

This way you have a program with one table and two optional sets of values, and one a single place of conditional compilation (#ifdef").

 

The resulting code will be something like this.

#include <system.h>

#pragma config XINST = OFF
#pragma config SOSCSEL = DIG  
#pragma config FOSC = HS1
#pragma config PLLCFG = ON

unsigned short value;
unsigned char index = 5;

#define TABLE1
//#define TABLE2

/******************************************************************************/
unsigned char read_table(unsigned char index)
{		
	#ifdef TABLE1
rom unsigned char *table = {
	0x02,	0xF4,
	0x01,	0x4D,
	0x01,	0xF8,
	0x02,	0x8D,
	0x00,	0xE6,
	0x02,	0x0E,
	0x02,	0xD3,
	0x01,	0xD5,
	0x02,	0xCA,
	0x01,	0xEF,
};
	#endif

	#ifdef TABLE2
rom unsigned char *table = {
	0x02,	0xF4,
	0x01,	0x4D,
	0x01,	0xF8,
	0x02,	0x8D,
	0x00,	0xE6,
	0x02,	0x0E,
	0x02,	0xD3,
	0x01,	0xD5,
	0x02,	0xCA,
	0x01,	0xEF,
};
	#endif

index *= 2;
unsigned char hi_byte = table[index];
unsigned char lo_byte = table[index + 1];
return (lo_byte | (hi_byte << 8));
};
/******************************************************************************/

void main(void)
{
for (;
{
	value = read_table (index);
}	
}
/******************************************************************************/

Also you may want to avoid editing code to build one version or another.

You can create 2 projects with the same source code, one for "table1" and another for "table2".

Project for table1 will define "TABLE1" in the compiler options (-d TABLE1) and the project for table2 will define "TABLE2" (-d TABLE2)

 

BTW:

What was this #include "pic18f87k22.h" doing in your code?

Sourceboost will choose the correct header file to include based on the project defined device (you can see this by looking into "system.h").

 

 

EDIT:

I did get back for some more testing and noticed that the linker did remove the dead code of the unreferenced "read_table2" function and table2 along with it.

Or, at least, I was unbale to code/table on the final result.

 

 

 

Best regards

Jorge

Edited by JorgeF

Share this post


Link to post
Share on other sites

Hi

 

As I see it you are missing a couple of #ifdefs in this code sample.

 

In fact, in "main", you don't call one of the functions "read_table1/2" depending on your initial #define.

But the code for both functions with its tables is still part of the program.

...

Best regards

Jorge

 

Hi Jorge,

 

The reason for putting the tables into separate functions was only for test purposes to see the trade offs required between RAM and flash memory usage.

 

The idea was to simulate the read from the RAM arrays originally used without altering the basic flow of the main code too much. Using conditionals I naively expected that I could select only the required table and the whole function including the table would be removed by the optimizer when the function was unused.

I had already tried the single function with multiple conditionals as you suggest but, with at least four large 16-bit tables in the real project, it made that function unwieldy, even after forming the tables into blocks. As you say you end up with “#ifdefs” and ”#endifs” everywhere which I find difficult to manage when the code extends over several pages.

 

The read_table2 () purposely wasn’t called in the sample so that it would be removed during optimization and show that the table inside had remained intact. Check out the program memory after compiling and the 'extra' table will still be there.

 

Your last idea of using multiple projects using the command line define “–d” is a good one and one I must admit I hadn’t even considered.

 

The spurious #include "pic18f87k22.h" - Just put that down to cut and paste!

 

Kind regards

 

davidb

Share this post


Link to post
Share on other sites

Hi

 

The reason for putting the tables into separate functions was only for test purposes to see the trade offs required between RAM and flash memory usage.

I think this kind of tables in ROM or in RAM should be declared global. I allways do it by declaring them in a separate module and with a "static" modifier.

 

The idea was to simulate the read from the RAM arrays originally used without altering the basic flow of the main code too much. Using conditionals I naively expected that I could select only the required table and the whole function including the table would be removed by the optimizer when the function was unused.

I had already tried the single function with multiple conditionals as you suggest but, with at least four large 16-bit tables in the real project, it made that function unwieldy, even after forming the tables into blocks. As you say you end up with “#ifdefs” and ”#endifs” everywhere which I find difficult to manage when the code extends over several pages.

You can't get rid of the "#ifdef / #endif" declarations, but you can put it all in the same place instead of having them spread all around your code.Another option is to have the tables and their functions declared in separate "C" files and use the conditional compilation to choose wich one to include.

Or different projects, each one including a different module containing a specific table.

 

The read_table2 () purposely wasn’t called in the sample so that it would be removed during optimization and show that the table inside had remained intact. Check out the program memory after compiling and the 'extra' table will still be there.
Yes, I noticed that after looking at the generated "HEX" files.

It looks like the table declarations are somewhat detached from the functions during compilation, so the linker discards the function code but not the table.

This behaviour can be due to the "special" ways ROM tables are implemented in PICs, and probably will change from one PIC family to another.

I also noticed that this does not happen if the conditional compilation is used around the tables (my sample).

 

Your last idea of using multiple projects using the command line define “–d” is a good one and one I must admit I hadn’t even considered.
Been using the separate projects approach for almost everything that needs diferent configurations.

Different hardware releases for the same product,

Different products with the same controler board.

Same power controler for different grid power and frequency (220V/50HZ versus 110V/60Hz, versus .....).

.....

Specialy when I need to deliver the source code to the costumer. I prefer they don't need to edit the code to access the different product options.

 

The spurious #include "pic18f87k22.h" - Just put that down to cut and paste!
Been there done that :)

 

 

Best regards

Jorge

Edited by JorgeF

Share this post


Link to post
Share on other sites

Your content will need to be approved by a moderator

Guest
You are commenting as a guest. If you have an account, please sign in.
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.

Loading...
Sign in to follow this  

×