Dr. John 0 Posted February 27, 2012 Report Share Posted February 27, 2012 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 Quote Link to post Share on other sites
Pavel 0 Posted February 28, 2012 Report Share Posted February 28, 2012 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 Quote Link to post Share on other sites
Dr. John 0 Posted February 28, 2012 Author Report Share Posted February 28, 2012 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 Quote Link to post Share on other sites
Dave 0 Posted February 28, 2012 Report Share Posted February 28, 2012 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 Quote Link to post Share on other sites
Dr. John 0 Posted March 1, 2012 Author Report Share Posted March 1, 2012 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 Quote Link to post Share on other sites
Reynard 0 Posted March 1, 2012 Report Share Posted March 1, 2012 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 Quote Link to post Share on other sites
Dr. John 0 Posted March 1, 2012 Author Report Share Posted March 1, 2012 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 Quote Link to post Share on other sites
JorgeF 0 Posted March 1, 2012 Report Share Posted March 1, 2012 (edited) 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 March 1, 2012 by JorgeF Quote Link to post Share on other sites
Reynard 0 Posted March 2, 2012 Report Share Posted March 2, 2012 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 Quote Link to post Share on other sites
JorgeF 0 Posted March 2, 2012 Report Share Posted March 2, 2012 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 Quote Link to post Share on other sites
Dr. John 0 Posted March 2, 2012 Author Report Share Posted March 2, 2012 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 Quote Link to post Share on other sites
JorgeF 0 Posted March 3, 2012 Report Share Posted March 3, 2012 (edited) 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 March 3, 2012 by JorgeF Quote Link to post Share on other sites
Recommended Posts
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.