Hi All, Am trying to re-write a code in PLM51 to embedded C. There is a statement in PLM51 as below.
DECLARE TASK(17) STRUCTURE(PNTR BYTE,STATUS BYTE,DELAY WORD); DECLARE DELAY_HEAD BYTE AT (.TASK(0).PNTR); //ERROR LINE//
What i have understood from this is-- DELAY_HEAD is a byte variable which resides at the same location as that of TASK(0).PNTR.(From the PLM51 manual)
I have rewritten the same into C as below.
struct tsk { unsigned char PNTR ; unsigned char STATUS; unsigned int DELAY; }TASK[17]; unsigned char DELAY_HEAD _at_ &TASK[0].PNTR ;
But its giving error 221:non-constant case/dim expression. Plss help..!!
Please pay attention to the instructions for posting source code:
www.danlhenry.com/.../keil_code.png
How about using a union ?
Or have the C program just access task[0].pntr instead of delay_head.
By the way - note that when porting your PLM51 code to C, i _strongly_ urge you to switch case for your variables. All-capital letters are normally reserved for preprocessor symbols, and another developer who sees code with huge amounts of upper-case symbol names will get a heart attack while desperately trying to look up what your symbols "expands" to.
Porting is not really a beginner's job - precisely because it relies upon a thorough understanding of both the source and target languages.
The errors you are getting are due to basic 'C' programming issues.
Is this a commercial or hobby project?
For links to some essential 'C' reference material, see: blog.antronics.co.uk/.../
Note that a pointer in C is a completely different data type from an integer - even if the integer data type happens to have the same size as the pointer.
And a pointer in Keil C51 is even worse, since the 8051 processor have multiple memory regions that requires special types of pointers just to tell the compiler that it requires special assembler instructions to reach the specific memory region.
Without that knowledge, you would have a hard time making the port. Your checksum code (from the other post) requires a pointer to code memory. In this case, you need pointers to data or xdata (I don't actually know, since I do not know where you will place your variables when you port the application).
Note that switching memory model when compiling may hide some of these issues, but not really to your advantage. You really need to know and understand the meaning of a code pointer, or the implications of playing with data, idata, xdata or maybe pdata (besides having const variables stored in the code to save RAM).
Hi, The logic of Checksum here is clear to me. Pls s tell me how to rewrite the below statement in C.
DECLARE CONTROL1 WORD AT (7FFEH) CONSTANT (0FFFFH); /* checksum Eprom */
I have written the same statement in C as
code unsigned int CONTROL1 _at_ 0x7FFE;
But i dont know how to initialise the value FFFF to this variable. This is used in Checksum detection test code.
Thanks.
page 201 (9-26) c167 manual.
Note: RP0H cannot be changed via software, but rather allows to check the current configuration.
Any idea how to change this reset value so the pins in port 6 are just normal I/O pins ?
Wow - major forum bug.
Seems the forum have a temporary file with fixed name for storing posted text, so if two posts at the same time, everything breaks badly.
The above text, claimed to have been posted by me, is actually a post from this thread: http://www.keil.com/forum/18464/
Why do you not keep a specific subject in the thread you did create for that discussion? Your checksum thread is: http://www.keil.com/forum/18448/
Hi, I have solved the checksum error for now.. I have changed the memory model to large in the options of the compiler. My code for that part is now as given here.
unsigned char code MEM_VAL; unsigned int idata *MEM_PTR = &MEM_VAL; /*Warning 259:-Diff pointer mspace */ unsigned int idata CHECK; unsigned int code CONTROL1 = 0xFFFF; for(MEM_PTR=0x0000;MEM_PTR<=0x7FFD;MEM_PTR++) { CHECK=CHECK+MEM_VAL; PCON=0x10; T3=0x0DF; } CHECK=CHECK+0x0FF+0x0FF; if(CHECK!=CONTROL1) { INITIAL_ERROR=90; }
and then selected the linker as BL51 in options and gave a statement as below in the "BL51 Locate".
CODE(?CO?CONTROL1(07FFEh))
As of now there are no errors except for the warning mentioned above.I am trying to remove the warning now. Thanks.
First off - you don't need to change memory model just to get a large pointer.
Secondly, the processor have multiple memory regions - each memory region requires specific instructions to access the data. MEM_VAL is specified "code". Where in your code do you think you instruct the compiler that MEM_PTR is expected to point into the "code" memory region?
What do you think happens when the compiler looks at the type of pointer, and inserts assembler instructions accessing one memory area while the intended values are actually in a compiletely different memory area.
data, idata, code, xdata, pdata really are important for you to understand. Actually vital to understand. Because address 0 in one of these memory regions is a different memory cell compared to address 0 in another memory region.
Indeed - these are absolutely fundamental to any use of any 8051-derivative!
"address 0 in one of these memory regions is a different memory cell compared to address 0 in another memory region"
There are a few cases where the regions overlap - it is left as an exercise for the student to think about which these may be.
It is also possible for the external hardware interface to make (some of) the external memory ranges overlap...
"It is also possible for the external hardware interface to make (some of) the external memory ranges overlap..."
Yes, sometimes xdata may for example be aliased with code for IAP support. And sometimes to allow the processor to download and run code from RAM. But knowing about the different memory regions and checking the datasheet to see if a specific chip have any optional extras is absolutely vital.
Indeed - quite so!
"and checking the datasheet to see if a specific chip have any optional extras"
Of course.
Hey, Thankyou for all the help so far. I have compiled my code and now... Its showing...
compiling ****.c linking... ****.obj To **** RAMSIZE(256) CODE (?CO?CONTROL1(0x7FFE)) WARNING L16 WARNING L16 ERROR L110 RESTRICTED VERSION WITH 0800H BYTE CODE SIZE LIMIT;USED:3014H BYTE LINK/LOCATE RUN COMPLETE.2WARNINGS,1ERROR(S)
Then there is one more fatal error shown in the end.
FATAL ERROR L250:CODE SIZE IN RESTRICTED VERSION EXCEEDED
I am using the student version of KEIL.So are these errors and warnings due the size limit issue?or some other problem???Because i cannot convert this code to a HEX file this way.
RESTRICTED VERSION WITH 0800H BYTE CODE SIZE LIMIT; USED:3014H BYTE
It tells you that you have a 0800H-byte limit, and have used 3014H bytes - in what way is that not clear?
Again, it tells you that you have a restricted version, and you have exceeded the limit.
Hey, Now i have tried the code with the full version and hence the problem is solved. But the 2 warnings and 1 error still remains.
Warning L16 Uncalled Segment, Ignored for Overlay Process ?CO?CONTROL1 Error L110 Cannot Find Segment ?CO?CONTROL1
What is the reason for such an error..??Pls guide me.
Thanks
Uncalled Segment, Ignored for Overlay Process
Isn't that obvious?
Have you checked in your source code - do you think that it should be called from somewhere?
The C51 manual explains the segment naming conventions - so you can relate the segment name reported by the linker to your source code...
Hey,
I have to initialise a variable called CONTROL1 in code memory and locate the same in fixed address 0x7FFE.I have gone through many forums and the Keil user's guide.I have written as below.
unsigned int code CONTROL1 = 0xFFFF;
Then,To use the linker BL51, I have done it as below.
Options->(Am using BL51)BL51 locate->Code ?CO?CONTROL1(07FFEh)
Still the error is L110:Cannot find segment. Apart from the warning mentioned above. The functions mentioned in the warning are called in the program.I have gone through the source code. Pls help Thanks.
But is any part of the program accessing the variable CONTROL1?
Hey, CONTROL1 is a variable used in one of the functions which would be called in the main loop in the initialisation stage.It is used in the Checksum function.The microcontroller used here is 80552 which is a ROMless version and hence using external EEPROM. Thanks.
"CONTROL1 is a variable used in one of the functions which would be called in the main loop"
Why do you say, "would be" there?
Is it called, or isn't it??
Hey, Yes,The function(Named as test_hardw) is called in the main loop..!But CONTROL1 is a local variable inside the function,test_hardw.I dont know if that makes a difference. CONTROL1 takes the value 0xFFFF and has to be located in code memory location 0x7FFE.
Still the error is L110:Cannot find segment.
And you still haven't checked the obvious: do you have a segment by that name? Look into your map file (perhaps after temporarily removing that special linker directive).
If you do have such a segment: is that the one your variable is actually in?
Hi, As you have said,i have removed that linker directive and checked in the MAP file.Its given as here.
SYMBOL TABLE OF MODULE: mp15 (PMOB) VALUE REP CLASS TYPE SYMBOL NAME ..... LX51 LINKER/LOCATER V3.64 ..... 010030EBH SYMBOL CONST BYTE MEM_VAL 00000010H SYMBOL IDATA --- MEM_PTR 00000013H SYMBOL IDATA WORD CHECK 010030E9H SYMBOL CONST WORD CONTROL1
BASE START END USED MEMORY CLASS ========================================================== C:000000H C:000000H C:00FFFFH 002F1DH CODE X:000000H X:000000H X:00FFFFH 0001C8H XDATA I:000020H.0 I:000020H.0 I:00002FH.7 000002H.2 BIT C:000000H C:000000H C:00FFFFH 0001BEH CONST I:000000H I:000000H I:0000FFH 00006CH IDATA I:000000H I:000000H I:00007FH 000018H DATA
In the above table its given CODE memory class range as 0000-FFFF.But my EPROM size is 0000-7FFF.I have given that in the OPTIONS->TARGET->Off-chip CODE Memory as 0x0000,0x8000.Pls check this.
tHANKS
Hey, How do i know which linker to use??BL51 or LX51.I am using 80552 microcontroller.
So now you have some data, you can start answering the questions I asked. Let's start with: does that segment whose address you were trying to change actually exist in your program?
Pls check this.
It's your program. Check it yourself.
But here's a hint: what might that tickbox "Use Memory Layout from Target Dialog" on the Options->LX51 tab be about?
Hi, Now i have a doubt .. Actually CONTROL1 is a variable used in one of the functions called in the main program called PMOB.c. When the linker say CANNOT FIND SEGMENT,does it mean that its searching for a .c file named CONTROL1???? So i need to create another .c file named CONTROL1.c and then add this variable in that?
and then give
?CO?CONTROL(07FFEh)
command in Options->BL51 locate CODE TAB?? I tried making a seperate .c file named CONTROL with the variable CONTROL1 initialised to a value 0xFFFF as below
But the same variable is used in the function in main module PMOB.c and hence i need to declare it as
extern unsigned int code CONTROL1 = 0xFFFF;
in PMOB.c too?? Then it is giving Error L104 :Multiple Public Definitions and Error 110:Cannot find segment
Hey, Sorry.."CANNOT FIND SEGMENT" error is resolved for now.But wat do i do for the Error L104:Multiple Public Definitions. Pls help Thanks
When the linker say CANNOT FIND SEGMENT,does it mean that its searching for a .c file named CONTROL1????
Of course not. It means exactly what it says: it's looking for a segment with that name. How that segment got to have that particular name is up to you to find out. It is spelled out in the documentation, including how you can change it.
hence i need to declare it
Yes.
as
No. That's a definition, not a declaration. If you don't know even that difference, you're in no position to be tinkering with the linker like you're trying to.
View all questions in Keil forum