Hi,
I'm wondering if I am doing something wrong here. I am trying to store an array for a large 256 byte look-up table.
I have a pretty small 8051 MCU of 8 KB flash memory (IROM), 256 bytes internal RAM (IRAM) and 256 bytes on-chip external RAM (XRAM).
Prior to adding this look-up table, my current build from Keil reports:
"Program Size: data=54.1 xdata=0 code=1984"
I take that to mean I am using 54 bytes of IRAM, 0 bytes of XRAM, and 1984 bytes of IROM?
Here is the variable declaration I am using:
code unsigned char CRC8LookupTable[256];
When I define the CRC8LookupTable and populate values, I get the Segment Too Large error.
If you use "code" doesn't that store the values in ROM, which I should have plenty of space for?
Is there something else I need to add to that variable declaration?
Thanks -Tim
Just for sake of completeness, Andrew is right about the header, it is not ignored. I know because I just spent 15 minutes trying to massage the declaration and definition correctly.
To call the table from other files here is the final declaration and definitions I needed to use.
crc.h
//This holds the 256 possible byte combinations for the CRC8 polynomial. extern unsigned char code CRC8LookupTable[256];
crc.c
//This stores the lookup table in the program flash memory through the "code" unsigned char code CRC8LookupTable[256] = { 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 };
Bizarre, but it works and I can call it from other source files.
Bizarre, but it works and I can call it from other source files. what is bizarre about things working when they are done right?
I do not know if, for some reason, your original mess would be supposed to work, but a compiler that fails because of code in a header file is, in my opinion, bug free
@Erik -- If you were building a compiler, why would you treat the case where you put code and require that to be declared and defined in two places?
When are other variables used like that? I'm sure there is a reason from a compiler perspective, but from an end user perspective when you shift around fundamental behaviors like that, it seems a bizarre.
Have you ever read the definition of bizarre? It doesn't imply standard of "rightness" or "wrongness" -- it is just unusual, as in atypical usage of a variable in C...
When you say things are "right" with Keil's compiler -- it's pretty relative. I'm not getting metaphysical on a compiler. We aren't just a Keil C51 shop in my business.
PIC's compiler at least provides an error that you need to declare and initialize at the same time if you use const. In that sense, as being more clear does make it their compiler "better"? Maybe Keil could add a similar warning to their compiler, and make it easier to use. Doesn't seem like a crack-pot idea. Easier products for end-users, more end users who make more money using the tool... seems pretty straightforward.
Geez man - I don't get your snark. Do you work for Keil?
A compiler is a relative construct -- likewise conforming C standards. Whatever -- just a tool for a job. I don't have any religious zeal to software languages and standards. I try to write good code that is portable and re-usable. But I am all moving bits around for money. I'm surely not putting in a CRC routine, on a beautiful spring, just because.
I literally don't care how Keil wants to implement things. Seriously. Their product, their compiler -- whatever. They can do it anyway they want. I would wish maybe they illustrated this point a bit better in their documentation, and maybe called it out with a more direct warning in their compiler.
End of the day -- we are building a cheap device using an 8051 and we plan to move thousand of units a month using these 8051s and save a bundle of money versus a PIC based implementation on each unit. If I have to fiddle with some Keil C51 semantics, no biggie.
Forum post is here for the next user, to save them some time. Mission accomplished. I'm out. I won't respond to anymore.
Way to be a nice neighbor, man. Remind me NOT TO EVER ASK YOU FOR PAID CONSULTING. You never know who is on the other end of the forum. Maybe we need some really tight assembly for one of these low-end MCUs, we pay $130/hr for good assembly all day long...
I don't see how that is in any way bizarre?
That is the standard way that you would declare & define a variable in 'C'.
The Keil-specific 'code' qualifier is applied in exactly the same way as the standard 'volatile' and 'const' qualifiers.
c-faq.com/.../decldef.html
@Andrew
Qualifiers. Good word to learn, didn't know that. I told you I am not a C wizard.
Okay -- so, for volatile & extern and other qualifiers. You don't re-use them when you define the variables in the source, right?
I only use the qualifier for volatile in the declaration, right? (add in an extern if you want too!)
volatile unsigned char SomeData;
Now we go to the source, no more qualifier required since it is in the declaration in the header.
unsigned char SomeData = 1;
Great we got variable we can use safely with interrupts. But volatile qualifier required in the definition? How is that not bizarre, how qualifiers are used differently between these cases?
I'm sure their is a reason for the compilation process, but I'm talking about end user experience here of someone typing in text.
Then you have the example of CODE as a qualifier. It has to be used as a qualifier in both the declaration and definition unlike volatile?
For my knowledge, does Keil C51 treat the XDATA qualifier the same way?
I'm sure one day I'll need to tap into XDATA. I was looking at the memory model stuff and everything else while diving into this yesterday.
CONCUR WITH MR ERIK
No. Quite the opposite: you do "re-use" them!
The declaration must match the definition in both type and qualifiers
If you're sharing the declaration with other modules (and why else would you put it in a header file?) you add 'extern'
some.h
extern volatile unsigned char SomeData ;
some.c
volatile unsigned char SomeData = 1;
Only a definition can contain an initialisation.
Are you sure on volatile? I'm looking at some code from another programmer who built some PIC routines, and I see they use volatile on both the definition and declaration.
Are you sure that the compiler cares? If you add volatile to the definition or not when you initialize the variable, the compiler doesn't utter a warning / error either way. I'm sure there is some way (memory map or something) to see if the variable is being optimized or not.
But for extern, you clearly need it in the declaration....
I actually appreciate the help Andrew! This like a master class in qualifiers...!
I have no skin in the game -- if the compiler wants volatile in both declaration and definition. It can have them!
TECHNICALLY YOU DONT NEED THE EXTERN IN THE DECLARATION IN A HEADER (IN C) BUT IT IS COMMON TO SEE IT THERE.
STOP SHOUTING!
The 'extern' is only optional for function declarations (ie, prototypes):
www.youtube.com/watch
HA? You guys know this one?
Good stuff here today.
NO. VARIABLES TOO. CHECK YOUR DOCUMENTS MORE THOROUGHLY. OR TRY IT YOURSELF.
DID U CHECK? NOW I AM FINISHED PARTYING AND I CAN REPLY MORE. IF U MISS THE EXTERN IT IS A TENTATIVE DECLARATION. IN C YOU CAN HAVE MANY OF THEM. GO CHECK IT OUT AND LEARN SOMETHING.
Dude -- I have never even heard of tentative declarations, this might be getting closer to finally nailing this down:
en.cppreference.com/.../extern
I'll have to read through this. Sheesh, they need to make an order of operations diagram for this kind of thing with the compiler. Seriously.
Thumbs up!
I'll have to read through this. Sheesh, they need to make an order of operations diagram for this kind of thing with the compiler. Seriously. It's crap like this you get when people are more interested in showing how smart they think they are that in writing maintainable code.
@Eric
This is entirely my point! The way CODE as a specifier/qualifier is treated is probably/maybe not consistent with the Bible of C. Who cares... not me.
So when I call the syntax for CODE bizarre, maybe you shouldn't be so dismissive cause that C Language has got a whole-lotta side-loops and exceptions all over the place. Lot of hands have touched it over the years.
Honestly, as someone without a stake in the Bible of C -- I have been using tentative declarations (I didn't even know what they were called!) and they've been working. But that CODE qualifier doesn't work like that. Fine... that's why I asked.
In my mind, why would you want to double type declarations between headers and source code? Now if you change a qualifier, you have to update it in two places. Plus the extra time double typing everything?
I really don't care if you consider that wise or stupid either. No need for a debate. It's like a debate over how many spaces are in indent -- who cares...?
ALSO -- there is a very clearly typed implementation for the next guy to figure out from the post. Karma on me, to pay something back to the forum.
End goal: the MCU is moving bits, and the code is modular and reusable and compiles on whatever target I need.
Guess what -- we don't write everything in my business in C either, it's just one of many computer languages we use! All of them have warts, wrinkles, and oddities.