So, I am trying to put together two (rather involved) functions that calculate the DAC. My processing routine for CalcDAC1 and CalcDAC2 are more or less the same, but with different variables. Currently, I'm using global variables that are directly called from the routine. I would like to use the same functionality but send it the variables I want the program to use to process so instead of:
global variables: unsigned int var1a; unsigned int var2a; unsigned int var3a; unsigned int var1b; unsigned int var2b; unsigned int var3b; void main(void) { while(1) { CalcDAC1(); CalcDAC2(); } } void CalcDAC1(void) { //Do stuff with var1a //Do stuff with var2a //Do stuff with var3a } Void CalcDAC2(void) { //Do stuff with var1b //Do stuff with var2b //Do stuff with var3b }
I instead would like to do
void main(void) { while(1) { CalcDAC(var1a, var2a, var3a); CalcDAC(var1b, var2b, var3b); } } void CalcDAC(unsigned char var1, unsigned char var2, unsigned char var3) { //Do stuff with var1 //Do stuff with var2 //Do stuff with var3 }
Unfortunately, my particular function has about 7-10 variables (complicated equation with lots of variables) so it requires me to create a LOT of local variables for each iteration, which I don't have the local space for (if that's the right term). Instead, I would like to send it pointers to local variables (if possible).
I ASSUME it would look something like this:
void main(void) { while(1) { CalcDAC(*var1a, *var2a, *var3a); CalcDAC(*var1b, *var2b, *var3b); } } void CalcDAC(unsigned char *var1, unsigned char *var2, unsigned char *var3) { //Do stuff with var1 //Do stuff with var2 //Do stuff with var3 }
Is this correct or is this even possible in C? Is this something you can only do in C++? Any help with implementation you can give me would be greatly appreciated. Thanks!
Well, I'm about maxxed out on global variables as well. I've had to start using the idata register because the first 128k is more or less used up. This is how I was creating the struct:
struct { signed short var1; signed short var2; signed short var3; } DACStruct;
I am now getting an address overflow error. I tried to change these to idata like this:
struct { signed short idata var1; signed short idata var2; signed short idata var3; } DACStruct;
but got the following error(s):
SRC\VARS.C(40): error C258: 'var1': mspace illegal in struct/union SRC\VARS.C(40): error C258: 'var2': mspace illegal in struct/union SRC\VARS.C(40): error C258: 'var3': mspace illegal in struct/union
Is there a way to place the entire struct in the idata rather than trying to break up individual parts of the struct? Or will I need to free up some space by moving other variables to idata to make room for this struct?
Also, when I want to send a pointer to the struct, I assume I'll want to do the following:
void main(void) { DACStruct->var1 = 1; DACStruct->var2 = 2; DACStruct->var3 = 3; CalcDAC(*DACStruct); } void CalcDAC(struct *DACStruct) { // do stuff with struct here }
I think I'm implementing the second part wrong but I'm not sure. At this point, I'm trying to get the basics down.
Does it look like this is the best approach for what I'm trying to do?
You can't use idata on individual members of a struct data type - it's the struct type or the struct variable that should be idata.
Next thing is that DACStruct isn't a pointer. So no -> to access the member fields in main. It is only your function that receives a pointer to DACStruct that needs to perform pointer indirection.
So you're saying the declaration should look like this:
idata struct { signed short idata var1; signed short idata var2; signed short idata var3; } DACStruct; void main(void) { DACStruct NewDACStruct; NewDACStruct->var1 = 1; NewDACStruct->var2 = 2; NewDACStruct->var3 = 3; CalcDAC(NewDACStruct); } void CalcDAC(DACStruct NewDACStruct) { // do stuff with struct here }
Is that correct?
It doesn't appear that creating a struct locally would save you a lot of local variables. Would it make more sense to create a global variable like this:
idata struct { signed short idata var1; signed short idata var2; signed short idata var3; } DACStruct; DACStruct idata NewStruct; void main(void) { NewDACStruct->var1 = 1; NewDACStruct->var2 = 2; NewDACStruct->var3 = 3; CalcDAC(*NewDACStruct); } void CalcDAC(DACStruct idata *NewDACStruct) // not sure if the idata portion is necessary here { // do stuff with struct here }
Note that struct { ... } xx creates a variable xx - not a data type xx.
You create a type with struct xx { ... } or with typedef struct { ... } xx;
Next thing - no use to have local variable in main() since variable lives full program time and still have to b e made global.
SO make a global variable ( not pointer) and access it in main.
I don't completely follow. Can you show me what you're referring to in reference to the example code I've given? It's pretty basic code and would help me understand what you mean a lot easier. This is mainly because I don't know what you're referring to when you mention
{ ... } xx
or
xx { ... }
typedef struct { ... } xx
Thanks for your help!
Is this what you're referring to?
idata struct { signed short idata var1; signed short idata var2; signed short idata var3; } DACStruct; void main(void) { DACStruct->var1 = 1; DACStruct->var2 = 2; DACStruct->var3 = 3; CalcDAC(DACStruct); } void CalcDAC(idata struct DACStruct) // not sure if the idata portion is necessary here { // do stuff with struct here }
Also, are the idata portions (highlighted in bold/red) necessary?
struct { int a; int b; } my_struct_variable; // <= this is a variable. struct my_struct_type { // <= this is a data type - not a variable. int a; int b; }; struct my_struct_type a_variable; // <= create a variable of this type. typedef struct { int a; int b; } my_struct_type2; // <= also a data type. my_struct_type2 settings_1,settings_2; // <= two variables of this custom type. int my_special_function(my_struct_type2* settings) { return settings->a + settings->b; // now have a pointer to a struct, so -> for pointer indirection. } void main(void) { settings_1.a = 1; // <= my_struct_variable is not a pointer, so no ->. settings_1.b = 1; my_special_function(&settings_1); settings_2.a = 2; settings_2.b = 3; my_special_function(&settings_2); for (;;) ; }
idata struct { signed short idata var1; // <= what would idata mean here? signed short idata var2; // <= you can't split the inside of a struct into signed short idata var3; // <= multiple memory regions... } DACStruct;
You just can not have idata inside a struct - if you could, then you would be able to specify different memory specifiers for different fields. But how would a linker be able to explode a struct to store the data all over the place?
The only time you can play with memory modifiers inside a struct, is if that struct has pointer members. Because the pointer can point at data in another memory region.
So for my example, this is what it would look like:
typedef struct // I'm creating a data type here { signed short var1; signed short var2; signed short var3; } DACStruct; DACStruct idata DACStructVar; // I'm creating a variable based on the DACStruct here. This will create it in the idata register void main(void) { DACStructVar.var1 = 1; DACStructVar.var2 = 2; DACStructVar.var3 = 3; CalcDAC(&DACStructVar); // Should I be using a pointer here or should I be directly calling DACStructVar here? } void CalcDAC(DACStruct idata* MyDACStruct) // Did I want a pointer here? { // do stuff with struct here }
Am I using the idata sections correctly? Did I want to use pointers with this or should I be directly calling the DACStructVar in the CalcDAC routine (DACStruct or &DACStruct)? Thanks for your help, I think I'm getting closer now!
Ok, that makes sense. So my last post is probably the correct way of doing it? Create the struct type with just signed shorts and then create a new variable of struct data type in the idata portion?
You are asking a lot of questions - aren't you spending time reading the compiler manual, or writing code and testing?
To answer your question, yes, I spend a lot of time writing code and testing it. The whole reason I originally came here is because I am maxed out on global variables in the data register and need to start using the idata register. Unfortunately, I don't know the correct way to setup things like structs in the idata register (which I think I understand a bit now).
Most of my recent questions have been clarifying what you're suggesting for me. I don't fully understand some of what you're asking so I'm creating example code to demonstrate this (my code looks nothing like the examples I'm giving. My current code is about 6k).
I have a number of different projects I am working on at the same time. At this point, I'm doing research on the best way to approach this portion of it. While I've been asking questions here, I've been working on other parts of my code. I didn't realize posting in these forums was going to be such a nuisance.
My experience with forums has typically been as long as it's for learning and you're not expecting other people to write your code for you, people are generally pretty helpful. My questions have fallen into that category for the most part (with the only request for code pertaining to suggestions I didn't fully understand the implementation of).
Is it a problem to ask a lot of questions in a forum that is, for the most part, pretty dead? Or is there a better place to ask these questions?
because I am maxed out on global variables in the data register and need to start using the idata register. they are not registers, they are memory areas
Is it a problem to ask a lot of questions in a forum that is, for the most part, pretty dead? Or is there a better place to ask these questions? For a '51 question not related specifically to Keil a better place might be http://www.8052.com/forum/.
back to your question: there are many address spaces in a '51 CODE register banks BDATA DATA IDATA SFRs XDATA
you need to fsmiliarize yourself with the processor, an the best place is "the bible" chapters 1, 2 and 3, you can find a link here www.8052.com/.../120112
Erik
Heh, thanks for the reply. I wasn't sure of the word I needed (as stated in previous posts) but I had a feeling "register" was the incorrect word.
Regarding the chip/code I'm using, just to specify based on what you share, I am using a M8051W chip, which has 256 bytes of on chip RAM so I have:
8K code space (I am currently utilizing just under 7K of it) 128 bytes of Data space (which is all used up) 128 bytes of Idata space (of which I'm using approximately 62 bytes of it) No Xdata on my chip The ESFR and SFR registers are all assigned to various functions of the chip
Right now, I seem to be juggling between data/idata space and code space so I'm trying to find the most efficient ways of doing so, hence why I come to this forum. I can mickey mouse my code and MAKE it work but I'd rather learn how to do things correctly from people who have coding experience, hence why I came here.
Thanks for the links you gave me. I will check them out. Thanks for the help!
On a sidenote, is there any reason everything designed by Keil or anything related to the 8051 looks like it was designed in the 90's? Every tool or forum looks extremely dated. Is that because long time programmers don't like changes or are the developers unable/unwilling to update the look/feel of the program? For a $2k-3k piece of software, you'd think they'd want to make it look a bit more up to date.
The 8051 was designed significantly earlier than that!
"Is that because long time programmers don't like changes"
More likely, Engineers are more interested in function than form/style
"For a $2k-3k piece of software, you'd think they'd want to make it look a bit more up to date"
I'd be far more concerned that it works well than that it looks "cool" (sic).
If I go to a shop and buy a brand new hammer, it's unlikely to look much different from my Grandfather's hammer...
I see your point regarding functionality over looks, I do. But why can't it be both? Why does it have to be a choice of looks over functionality?
And I wasn't just talking about the 8051 specifically. Every website (from this one to the 8052 forum) just looks extremely dated and it's not as functional as many other websites.
While your metaphor with the hammers is technically true (hammers are shaped the same), hammer "technology" has been updated so you have different types of handles, material type, weight balances, etc. And that's kind of my point. We can keep the technology the same but for the price of the software, can't it look good too?
Because a vendor of PC tools can sell 100k+ licenses.
How many licenses do you think Keil get to sell of their embedded tools?
How much staff do you think they have to put on cosmetic tasks? How would that affect the already quite significant price?
I honestly have no idea of Keil's yearly license numbers, but if any of you had a ballpark idea of what the numbers were, I'd be interested in finding out.
http://www.keil.com/download/files/8051_market_in_2008.pdf
[ It was 2008. ]
The Development Tools: Problems in long term support of a given architecture usually happen when development tools become stale or are lost entirely. This happens when active support for devices dies away and is no longer kept up to date. Interest is lacking since many of the players have started in newer, more profitable and more exciting ventures. Engineers and tech support have often moved on to new jobs and their skills and knowledge move with them. Some firms rely on residual sales and do very little or no new development and few activities other than maintaining a website and a series of reps who sell other complementing products. But the 8051 market is still interesting and profitable for many players. For one, Keil continues with on-going support and product development. This is not likely to end soon. There are other companies that operate in the same fashion. Certainly, there are enough of them to sustain the 8051 tools industry. It can also be argued that there are more, better and cheaper development tools available today for the 8051 than in the first few years after its birth.
Compilers: Compilers are the key focus of any microcontroller tools chain. Compilers are first on the purchase list once the chip is selected and everything else follows. Nearly everybody has to buy a compiler. A few might purchase only an assembler and it is doubtful anyone hand codes assembly anymore. Other components such as in-circuit emulators and RTOSs are nice options, but not an absolute necessity. A premium compiler is important because of the limited resources of the 8051. Code size in particular is important because of the small amount of ROM available. Atmel has a few parts with only 2Kbytes and this can be a tight fit for any project. Banking schemes to increase memory size need to be fast, easy to implement and robust. A good compiler can help you get the appropriate code size and speed balance in your project. RTOS support is tricky because of the limited stack. Keil C51 excels in these aspects and is why it has become the de facto standard around the world. Many compiler companies see the 8051 as steady or very slowly increasing. Keil’s 8051 business is substantial and active development work is still being done. There are few (maybe no) bugs in the compiler but Keil engineers are kept busy installing new devices in their Device Database®. At the time of this writing, it is estimated to take a Keil engineer 3 to 4 days to enter all the new 8051 devices and companies from the last few months into the database ! Plus there are always a few companies changing 8051 components such as interrupts, data pointers and the way the stack is implemented. These changes must be accommodated for by the compiler. Other compiler companies claim to have great and increasing 8051 business but this is difficult to confirm accurately because of competitive secrecy. It is rather easy to make spurious marketing and sales claims.
For a $2k-3k piece of software the price of a software is (devlopment costs + administration costs + profit)/number of sales.
I have used outright miserable software the cost far more, but the number of users being so small that there was nothing to do about it.
or are the developers unable/unwilling to update the look/feel of the program? For a $2k-3k piece of software, you'd think they'd want to make it look a bit more up to date.
If Keil were to work on non-core issues (the core being compiler, assembler, linker) I would much rather have them supply a decent editor.
anyhow, that is a minor concern as long as the core works as expected.
your concern for a "cool' look show inexperience, anyone with experience could not give a hoot.
There are plenty of functional compilers that look like they made in at least the last decade. Both Microchip AND Atmel's compilers look good AND are completely functional. What other compilers have you tried, Erik? I'm not doubting your experience (clearly you know a lot about these), I'm just curious as to what other software you've used that is so superior to keil.
I'm going to ignore the implication that, because I want a compiler that looks like some effort was put into it's appearance somehow makes me inexperienced . . .
I'm just curious as to what other software you've used that is so superior to keil compiler, assembler, linker ARM/c51: none editor: Brief, CodeWright.
Heh, sorry about that, I wrote that wrong. I meant what software you used that was so INFERIOR, not superior (you had mentioned that you used a lot of abysmal software).
I meant what software you used that was so INFERIOR, not superior (you had mentioned that you used a lot of abysmal software).
Nothing you are likely to run into, nothing with widespread use, things like e.g. J1708 analyzers (costly), some ICEs(costly), most freeware I have tried, ....
Any chance you've tried Atmel Studio or Microchip MPLab? Both of those are examples of free software that are functional and look good. To be fair, I am pretty familiar with Atmel Studio so it's my basis of comparison for most development platforms, which is partially the reason why I'm disappointed by the layout and implementation of Keil. I do like some of the features of Keil (like the built in UART analyzer) but there are some things that are completely frustrating about it (like if you add in a line of code, it moves all your breakpoints so the breakpoints aren't actually pointing to a specified line of code but rather the line the code is placed on, which seems a bit ridiculous to me).
Regardless, I look at free software like Atmel Studio that manages to be functional (sometimes more so than Keil) and looks good and don't really understand why Keil, who charges $3k for software, can't update the looks of the software. But then again, I guess Atmel makes up their software costs from the money they make on their hardware so I guess it's not exactly comparing apples to apples.
Like you said, if it's functional, looks don't matter all that much but if you have a good piece of software, it would be nice to have it look updated as well. But I guess your (or someone else's) explanation on further driving up costs makes sense as well. Oh well.
Both of those are examples of free software that are functional and look good. Free??? they are paid for by a charge to the cost of the chips.
I guess it's not exactly comparing apples to apples. agreed, wrote the above before I read this line
Like you said, if it's functional, looks don't matter all that much but if you have a good piece of software, it would be nice to have it look updated as well. But I guess your (or someone else's) explanation on further driving up costs makes sense as well. Oh well. It really is a case of where you want the developers to use their budget. I, personally, consider using budget (unless you have 'excess') to work on 'look', when you have other things to improve, totally wrong.
Budgeting 'look' really is a matter of competition and/or "user sophistication". If the competition is equally good and 'looks' a lot better any company will work on it. In some areas of software (specifically what is geared towards the non-sophisticated user) 'look' has a high priority.
View all questions in Keil forum