Jump to content
Dr. John

Array Allocation In Rom Also Removes Ram Space

Recommended Posts

I have been reviewing BoostC in preparation for purchasing a Pro license in support of a project. While in general I like what I see, there is a bug that will prevent me from the purchase if it isn't fixed.

 

The bug is that when declaring an array in ROM, space for same array is allocated in RAM even though it isn't used, thereby removing the availability of this RAM. Here is an example.

 

rom char *LCD_segment_config[12] = // LCD segments setting table

// if bit = 1, then pixel is enabled

{ // GFEDCBA

0b00111111, // for displaying '0'

0b00000110, // for displaying '1'

0b01011011, // for displaying '2'

0b01001111, // for displaying '3'

0b01100110, // for displaying '4'

0b01101101, // for displaying '5'

0b01111101, // for displaying '6'

0b00000111, // for displaying '7'

0b01111111, // for displaying '8'

0b01101111, // for displaying '9'

0b01111001, // for displaying 'E'

0b00000000 // for displaying ' '

};

 

The code generated will correctly access this table. However, if one looks at the memory map you can see the following.

 

Register usage

==============

 

Address Bit Lengh Bit Mask Unique Name Name

------- --------- -------- ----------- ----

00000000:00000008 gbl_indf0 indf0

00000001:00000008 gbl_indf1 indf1

00000002:00000008 gbl_pcl pcl

00000003:00000008 gbl_status status

00000004:00000008 gbl_fsr0l fsr0l

00000005:00000008 gbl_fsr0h fsr0h

00000006:00000008 gbl_fsr1l fsr1l

00000007:00000008 gbl_fsr1h fsr1h

00000008:00000008 gbl_bsr bsr

00000009:00000008 gbl_wreg wreg

0000000A:00000008 gbl_pclath pclath

0000000B:00000008 gbl_intcon intcon

0000000C:00000008 gbl_porta porta

0000000D:00000008 gbl_portb portb

0000000E:00000008 gbl_portc portc

0000000F:00000008 gbl_portd portd

00000010:00000008 gbl_porte porte

00000011:00000008 gbl_pir1 pir1

00000012:00000008 gbl_pir2 pir2

00000013:00000008 gbl_pir3 pir3

00000014:00000008 gbl_pir4 pir4

00000015:00000008 gbl_tmr0 tmr0

00000016:00000008 gbl_tmr1l tmr1l

00000017:00000008 gbl_tmr1h tmr1h

00000018:00000008 gbl_t1con t1con

00000019:00000008 gbl_t1gcon t1gcon

0000001A:00000008 gbl_tmr2 tmr2

0000001B:00000008 gbl_pr2 pr2

0000001C:00000008 gbl_t2con t2con

00000020:00000060 gbl_LCD_segment_config LCD_segment_config

0000002C:00000010 gbl_xxxxxxxxxxx xxxxxxxxxxx

 

The assembly code also contains this allocation.

 

In fact, when first trying to compile and link code that I had written for the Hi Tech compiler, it wouldn't link, even though I was sure I was within the Lite license limitations. This was apparently because I had also included two additional larger tables that resulted in a RAM allocation more than sufficient to violate the Lite license limitations.

 

I am not sure if this happens every time, but I consistently had the problem of violating the Lite license limitations until I started out with essentially a one line do-while loop in the main routine, adding a bit of code at at time until I found this. I expect that it is 100% reproducible.

 

The expected behavior is for the tables to be allocated in ROM, but not be allocated in RAM since no reference to RAM is required for reading elements of the table.

 

I am using the BoostC Optimizing C Compiler Version 7.05 (for PIC16 architecture) and corresponding linker.

 

I appreciate the effort you guys are putting forth to make this compiler available and robust.

 

 

Dr. John

Share this post


Link to post
Share on other sites

Rom specifier can be used with char and char* types only. Your code tries to use it with array of pointers and this is not supported. Take a look at the 'Rom' chapter in BoostC help for more information.

 

Regards,

Pavel

Share this post


Link to post
Share on other sites

Pavel,

 

Thanks for your rapid reply.

 

Well, the form of the declaration matches exactly that shown in the BoostC manual, as shown on page 45. Originally I had declared the array without the pointer (i.e.,

 

rom char LCD_segment_config[12] = // LCD segments setting table

// if 1, then pixel is enabled

{ // GFEDCBA

0b00111111, // for displaying '0'

0b00000110, // for displaying '1'

0b01011011, // for displaying '2'

0b01001111, // for displaying '3'

0b01100110, // for displaying '4'

0b01101101, // for displaying '5'

0b01111101, // for displaying '6'

0b00000111, // for displaying '7'

0b01111111, // for displaying '8'

0b01101111, // for displaying '9'

0b01111001, // for displaying 'E'

0b00000000 // for displaying ' '

};

In any case, the form of declaring the array doesn't seem to make any difference. In both cases, the compiler buys the declaration and seems to do the same thing, i.e., create code that will correctly access the table (which is created correctly in ROM), but also allocate the space that would be used by the array in RAM and thereby rob this space.

 

I still think that this is a real bug. Also, some clarification of the correct/preferred way of declaring the array would be appreciated. I, like you, think that declaring it as per my original message is equivalent to declaring an array of pointers, but the manual speaks differently. Worse, (or better?), the compiler doesn't seem to distinguish between the two.

 

Thanks again for your hep.

 

Dr. John

Share this post


Link to post
Share on other sites

Well, the form of the declaration matches exactly that shown in the BoostC manual, as shown on page 45. Originally I had declared the array without the pointer (i.e.,

Your code is not quite as the example of page 45..

 

The following will do what you want:

#include <system.h>
rom char* LCD_segment_config = // LCD segments setting table
// if 1, then pixel is enabled
{ // GFEDCBA
0b00111111, // for displaying '0'
0b00000110, // for displaying '1'
0b01011011, // for displaying '2'
0b01001111, // for displaying '3'
0b01100110, // for displaying '4'
0b01101101, // for displaying '5'
0b01111101, // for displaying '6'
0b00000111, // for displaying '7'
0b01111111, // for displaying '8'
0b01101111, // for displaying '9'
0b01111001, // for displaying 'E'
0b00000000 // for displaying ' '
};

void main()
{
   char zero;
   char one;
   zero = LCD_segment_config[ 0 ];
   one = LCD_segment_config[ 1 ];

   while( 1 );
}

 

Regards

Dave

Share this post


Link to post
Share on other sites

Gentlemen,

 

Again, thanks for your attention to this.

 

I have tried all three variations of the source code and receive identical results in the assembly code generated as well as the map file generated by the linker.

 

The generated assembly code correctly puts the table in ROM, and correctly accesses it. However, in addition, it incorrectly allocates space for the table in RAM, which incorrect allocation follows through into the map file generated by the linker. Hence, were I to put a couple of larger tables (which is indeed my intent) in ROM, the result would be that I would have zero RAM available for anything else, even though it isn't being used. I'm hoping that you will address this issue since it is the main issue of this post and the main issue for me to have resolved prior to making a license purchase.

 

Regards,

 

 

Dr. John

Share this post


Link to post
Share on other sites

Hi Dr John,

 

If you use the method which Dave describes you should only have a single byte allocated in RAM for each array created in ROM. This byte contains an index for the function that retrieves the data from ROM.

 

The map file should only show 8 bits (why bits I won't ask).

 

This map is for 2 different LCD lookup tables:

00000020:00000008			 gbl_LCD_segment_config1		  LCD_segment_config1
00000021:00000008			 gbl_LCD_segment_config2		  LCD_segment_config2

 

Cheers

 

Reynard

Share this post


Link to post
Share on other sites

Hi Reynard,

 

Thanks for your input. What you said makes a lot of sense to me. However, what ACTUALLY happens is different. I get the following:

 

00000020:00000060 gbl_LCD_segment_config LCD_segment_config

 

This is the problem that needs to be resolved. This result is completely independent of the presence/absence of the asterisk and its location (within the range of options presented here). Meanwhile, as I said before, the table is correctly created in ROM and the code to access it is as well. So, it seems like the compiler understands half of the issue, but not the other half.

 

I'm hopeful that this will be eventually realized as a real bug and not a user error.

 

 

Dr. John

Share this post


Link to post
Share on other sites

Hi John

 

After a bit of testing, I think I understand what is happening.

 

You are declaring your table with a double indirection. In other terms, you are setting up an array of 12 pointers to char.

Remenber that "char* x[]" is semanthically equivalent to "char** x".

So the compiler is putting the table in ROM, but also setting up an array of pointers to that table in RAM.

 

Change your table declaration from

rom char *LCD_segment_config[12] = {.....};

to

rom char *LCD_segment_config = {.....};

 

just drop the "[12]" and you get it right..

 

 

Best regards

 

Jorge

(Dr.)

Edited by JorgeF

Share this post


Link to post
Share on other sites

Hi Dr. John,

 

SourceBoost is a bit weak with data stored in ROM. I am not sure it should be called an array since you cannot declare it as an array but merely a string if chars.

 

I would like to see it expanded in to retrieving all data types including structures particularly for the PIC18 devices which have large ROM space.

 

Why SourceBoost stores the "string" index in RAM ? I can't see a reason for it at the moment since it seems to be a fixed value starting at 0 and incrementing by 1 each string declaration. Couldn't it just be a constant and save RAM and extra instructions.

 

SB is still value for money despite a few limitations.

 

Cheers

 

Reynard

Share this post


Link to post
Share on other sites

Hi Guys

 

I think SB limitations for storing data in ROM, are related to the way it can be retrieved.

 

Small PICs don't have ROM access, so the way to get to the data is by means of the so-called "lookup tables" (microchip data sheets) build around the RETLW instruction alongside with some PCL maths.

By inspecting the ASM code generated by SB, we can easilly find those "lookup tables".

By the way, it seems that SB joins multiple ROM arrays in a single table; so the RAM byte is really a base offset for each rom array in a single table.

 

Midrange PICs with EEPROM, can access data in ROM the same way that they access data in EEPROM, this makes it easier than using the RETLW instruction, but still has some limitations.

For instance, most of the ROM words are 14 bits wide. Either we store bytes and forget the extra 6 bits, or store bitstrings splitted in 14 bit segments and rebuild the original bytes and words when retrieving the data.

Anyway, the access to full data structures would be a bit awkward and would cost a number of processing cycles that can't be disregarded.

 

In all cases, the data retrieved from ROM, needs a RAM variable to act as a buffer, before data can be used.

 

 

FWIW, based in a few years of experience programing PICs in ASM and squezing code and data to use allways the smallest PIC possible in projects were we fight to save 1 or 2 cents on the final product; I think SB does a really good job.

 

 

Best regrads

 

Jorge

Share this post


Link to post
Share on other sites

Jorge and Reynard,

 

Great stuff!

 

Jorge, you are right. The only way that the compiler will deliver the correct results is if you declare the array as a string. I think that this is a bug, but there is a reasonable workaround and I'd really like to use this compiler since the Hi Tech compiler seems to create more than double the number of instructions (and at least double the amount of execution time) to accomplish the same thing.

 

Reynard, you confirm Jorge's understanding and your comments were necessary for me to catch Jorge's initial comment to DELETE the brackets. I had tried to compile with the brackets in place, but empty, and got the same results as previously.

 

This raises the following question to a couple of guys who seem to have a fair amount of experience with SourceBoost's products: What is your experience of the responsiveness of Dave and Pavel to issues such as these? I see that they monitor the board and provide initial feedback fairly quickly, but if there are issues that need fixing, are they responsive? What have been your experiences?

 

Thanks again for your help.

 

 

Dr. John

Share this post


Link to post
Share on other sites

Hi

 

...... I think that this is a bug, but there is a reasonable workaround .........

 

I'm sorry to disagree.

I think this is a good solution to save RAM by storing static data in ROM (program memory) in the only way suitable to the PIC architecture. There is a big difference bettwen a real ROM (or EPROM) and the PIC program memory.

The word "rom" used as a storage class specifier might be misleading at begining.

In reality what it does is not store data in a non volatile memory, what it does is stuff data in program instructions, what is quite diferent.

The only kind of non-volatile storage available in PICs that ressembles the RAM storage is the EEPROM, even so the access is not exactly as straightforward as the RAM.

 

This raises the following question to a couple of guys who seem to have a fair amount of experience with SourceBoost's products: What is your experience of the responsiveness of Dave and Pavel to issues such as these? I see that they monitor the board and provide initial feedback fairly quickly, but if there are issues that need fixing, are they responsive? What have been your experiences?

 

Well, its not exactly the case with me.

As dispointing as it may sound, I'm only started to discover the SB compiler a couple of weeks ago. What looks like SB experience is mainly the porting of general knowledge obtained somewere else on other tools and technologies to a few hours of testing the SB compiler and analysing the Assembly code it generatesby comparision to the the way I would have wrote it.

 

About your question.

By what I discovered in this forum and the releasing rate of new revisions, I'm the feeling that the SB team responsiveness is as good as any other. Probably better than some others that I already come across. Some of them under a much higger price tag.

 

Thanks again for your help.

 

You're welcome

 

 

Best regards

 

Jorge

Edited by JorgeF

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

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.

Loading...

×
×
  • Create New...