We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I have searched the entire knowlege base and have not found an answer to a specfic question.
how do you CAST a generic pointer to a memory specific pointer.
There are examples in the manual for casting a memory specific pointer to a generic, but not the other way around.
Specifically, I have an array of generic pointers to structures. the array is located in xram. I have found a bug in the compiler where in it gets confused as to what kind of pointer it is dealing with (more later). If I could type cast the pointer to generic it would most likely fix the problem.
The problem I'm currently up against, is the following where the compiler only generates the 0xFF identifier for a generic pointer when assigning a generic pointer read out of an array, to a generic pointer. to wit:
Below, is an abbreviated source. I'm not sure if this will exhibit the problem if compiled or not, but my code that uses the same lines of code below fails. Specfically in this example, at address 37F The compiler fails to copy a generic pointer into another generic pointer. All it does is load the memory type specifier into the pointer. This is a 7.5 compiler.
The target part is a silabs 040
very strange problem with indexing and pointers. Given the following structures, the code below breaks.
Sample values as examined in the silabs debugger show
in xdata, there is an array of pointers that is copied from flash. After the copy the table looks something like this 32B 32C 32D 32E 32F 330 0xFF 0x02 0x01 0xFF 0x0A 0xB8 the result of the code is that
current_treatment winds up with the following in it. 0xFF 00 00 00
the table is at 0x032B current_mode = 1;
Here is the listing code. As you can see, this does not copy the pointer, just the type. Something is clearly wrong here. In other versions of this, that I was debugging prior to compiling this one, I was seeing it index by 2, and pick up the values that way, which resulted in the current_treatment holding 0x01FF0A2B which is also wrong.
0361 7800 R MOV R0,#LOW current_mode 0363 E2 MOVX A,@R0 0364 FF MOV R7,A // here R7 = 1 0365 33 RLC A // double it 0366 95E0 SUBB A,ACC // results in 0 ! 0368 FE MOV R6,A // R6=0 0369 EF MOV A,R7 // ACC now = 1 036A 25E0 ADD A,ACC // ACC now = 2 (should be 3) 036C FF MOV R7,A // R6R7 now are 0002 036D EE MOV A,R6 // since the value is 1, there will be nothing rotated into R6 036E 33 RLC A 036F FE MOV R6,A // R6R7 now are 0002 0370 7400 R MOV A,#LOW treatments // puts 2B into a 0372 2F ADD A,R7 // adds 2 to it resulting in 2D 0373 F582 MOV DPL,A // dp = 002D 0375 7400 R MOV A,#HIGH treatments // this puts 03 into A 0377 3E ADDC A,R6 // adds 0 to it resulting in 03 0378 F583 MOV DPH,A // dptr now is 032D 037A A3 INC DPTR // increments to 032E which is CORRECT 037B E0 MOVX A,@DPTR // picks up the 0xFF 037C 900000 R MOV DPTR,#current_treatment 037F F0 MOVX @DPTR,A // saves 0xFF. and never picks up anyting else ; SOURCE LINE # 2367 0380 ?C0034: ; SOURCE LINE # 2375 0380 120000 R LCALL LCDClearScreen ; SOURCE LINE # 2376 0383 120000 R LCALL L?0870
struct treatment_table idata * current_treatment; struct treatment_table xdata * scroll_treatment;
code struct treatment_table user_control= { 1, /* only one step */ 0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xff,0xff,0xff,/* infinite time */ }; code struct treatment_table single_pulse_zero_d= { 1, /* only one step */ 0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xff,0xff,0xff,/* infinite time */ };
struct treatment_table xdata * treatments[]= { &user_control, // This is a holder for the user mode. 8-12-08 &single_pulse_zero_d }; // // No memory specifier, means that this will be a generic pointer table, so it can point to xram OR code. // the compiler takes care of this, though it generates much slower code 8-21-08 // code struct treatment_table * treatment_tbl[]= { &user_control, // This is a holder for the user mode. 8-12-08 &single_pulse_zero_d };
unsigned char current_mode; main() { current_mode=1; // // copies the treatment table from flash into xram. I can't make the keil compiler do this automatically for me. // when xdata is examined, there is a table of GENERIC pointers there. Each pointer is 3 bytes long, and starts // with an 0xFF which is correct, it says that it is a generic pointer to code memory. // memcpy(treatments,treatment_tbl,sizeof(treatments)); // this works just fine // // This however fails. It indexes treatments by 2 bytes, rather than 3 bytes, so it gets bogus pointers into current // treatment // current_treatment is GENERIC pointer. So indexing into an array of generic pointers and assigning one to // current_treatment SHOULD index by 3's and put the entire pointer there.
current_treatment=treatments[current_mode];
}
This pointer idata struct treatment_table code * current_treatment; says that there is a pointer to CODE located in idata space.
struct code *foo; says that there is a pointer to CODE, but it is located wherever the keil compiler decides to put it, which is generally speaking data space. BUT it is a specific pointer, so it will be a 2 byte pointer.
struct *foo; says that there is a GENERIC 3 byte pointer, since there is no memory space specified.
xdata struct *foo; says there is a GENERIC 3 byte pointer that is specifically stored in xdata.
The trouble is that in my original code example, an array is created of generic pointers, and that array is copied to xdata. However, indexing into that array and assigning a GENERIC pointer from the array to another GENERIC pointer, indexes the array by 2 bytes, NOT by 3, and on top of that, it picks up ONLY the type byte, resulting the the destination pointer being a null pointer to code space.
The trouble is that in my original code example, an array is created of generic pointers, and that array is copied to xdata. However, indexing into that array and assigning a GENERIC pointer from the array to another GENERIC pointer, indexes the array by 2 bytes
I would imagine that you have forced the compiler to lose track of the memory space information associated with the pointers. You may find that you can rectify the situation with a bit of clever casting, but it seems better to me to avoid the situation entirely.
I checked an 11 year old copy of the compiler manual as well as the online version and both give examples of the syntax as follows:
Points to xdata, resides in default memory space: char xdata * a;
Points to xdata, resides in code space: char xdata * code a;
Points to anything (generic), resides in xdata: char * xdata a;
The memory space qualifiers are always placed immediately to either side of the '*'. I think that it was suggested to you that you are invoking ancient compatibility syntax with things like 'xdata char idata *a;' and I think that that suggestion was correct.
Best stick to the current standard syntax, and best not to try and outsmart the compiler.
I don't think it was suggested. I'm not trying to outsmart the compiler. Just get it to do what I need it to do. Here is a test file. This compiles, but agian it is not creating an array of generic pointers.
My original code created the array of generic pointers, but when given an index, it indexed by 2 bytes, not 3 bytes and only picked up the memory type specifier and not the address.
All I am trying to do is to create an array of generic pointers residing in XRAM, aid pointers need to be capable of pointing to any memory space, and access any of the generic pointers and put it into a generic pointer, and I'm not seeing the compiler do that.
if I remove the code in front of case1 then it puts that into external memory, but I have not been able to make my main program do that without having to do a memcpy
#include "C8051F040.h" #include "stdlib.h" struct example { unsigned char * name[10]; unsigned int flags; }; code struct example case1= { "123456789", 0xFEED }; code struct example case2= { "987654321", 0xDEAD }; xdata struct example case3= { "987654321", 0xBEEF }; // // array is in code space. // This version of the code doesn't create a generic struct array. // it creates a 2 byte pointer array, with case 03 haveing an address of 04 // in code space // code struct_array[]= { &case1, &case2, &case3 }; // // aray is in data space // xdata struct_array2[]= { &case1, &case2, &case3 }; xdata struct example xdata * pointer; xdata struct example code * pointer2; //idata struct example code * current_treatment; // was code //xdata struct example code * scroll_treatment; // was code extern void *memcpy (void *s1, void *s2, int n);// dest, sourc, length main() { unsigned int index; memcpy(&case3,&case2,sizeof(struct example)); index=1; pointer=struct_array2[index]; index=2; pointer2=struct_array2[index]; index=1; pointer=struct_array[index]; index=2; pointer2=struct_array[index]; }
I've compiled and built this test case using 7.5 of the compiler.
reading through your post again, I tried changing the pointers to
struct example xdata * xdata pointer; struct example code * xdata pointer2;
still no joy. The array is still not an array of generic pointers. And in particular, after the first assignment to pointer, it is a NULL pointer, and after the first assignment to pointer 2, it points to the two byte value that it read out of the array. It is still not a generic pointer.
My second point is that I would happily type cast the damn things to generic, but there is no such cast possible.
I did not know how to post source code here when I posted my first post. Here it is again but within the pre headers. you will notice that the compiler generates code that pics up the memory type only, and does not pick up the address.
Sample values as examined in the silabs debugger show in xdata, there is an array of pointers that is copied from flash. After the copy the table looks something like this 32B 32C 32D 32E 32F 330 0xFF 0x02 0x01 0xFF 0x0A 0xB8 the result of the code is that current_treatment winds up with the following in it. 0xFF 00 00 00 the table is at 0x032B current_mode = 1; Here is the listing code. As you can see, this does not copy the pointer, just the type. Something is clearly wrong here. In other versions of this, that I was debugging prior to compiling this one, I was seeing it index by 2, and pick up the values that way, which resulted in the current_treatment holding 0x01FF0A2B 0361 7800 R MOV R0,#LOW current_mode 0363 E2 MOVX A,@R0 0364 FF MOV R7,A // here R7 = 1 0365 33 RLC A // double it 0366 95E0 SUBB A,ACC // results in 0 ! 0368 FE MOV R6,A // R6=0 0369 EF MOV A,R7 // ACC now = 1 036A 25E0 ADD A,ACC // ACC now = 2 (should be 3) 036C FF MOV R7,A // R6R7 now are 0002 036D EE MOV A,R6 // since the value is 1, there will be nothing rotated into R6 036E 33 RLC A 036F FE MOV R6,A // R6R7 now are 0002 0370 7400 R MOV A,#LOW treatments // puts 2B into a 0372 2F ADD A,R7 // adds 2 to it resulting in 2D 0373 F582 MOV DPL,A // dp = 002D 0375 7400 R MOV A,#HIGH treatments // this puts 03 into A 0377 3E ADDC A,R6 // adds 0 to it resulting in 03 0378 F583 MOV DPH,A // dptr now is 032D 037A A3 INC DPTR // increments to 032E which is CORRECT 037B E0 MOVX A,@DPTR // picks up the 0xFF 037C 900000 R MOV DPTR,#current_treatment 037F F0 MOVX @DPTR,A // saves 0xFF. and never picks up anyting else ; SOURCE LINE # 2367 0380 ?C0034: ; SOURCE LINE # 2375 0380 120000 R LCALL LCDClearScreen ; SOURCE LINE # 2376 0383 120000 R LCALL L?0870 struct treatment_table idata * current_treatment; struct treatment_table xdata * scroll_treatment; code struct treatment_table user_control= { 1, /* only one step */ 0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xff,0xff,0xff,/* infinite time */ }; code struct treatment_table single_pulse_zero_d= { 1, /* only one step */ 0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xff,0xff,0xff,/* infinite time */ }; struct treatment_table xdata * treatments[]= { &user_control, // This is a holder for the user mode. 8-12-08 &single_pulse_zero_d }; // // No memory specifier, means that this will be a generic pointer table, so it can point to xram OR code. // the compiler takes care of this, though it generates much slower code 8-21-08 // code struct treatment_table * treatment_tbl[]= { &user_control, // This is a holder for the user mode. 8-12-08 &single_pulse_zero_d }; unsigned char current_mode; main() { current_mode=1; // // copies the treatment table from flash into xram. I can't make the keil compiler do this automatically for me. // when xdata is examined, there is a table of GENERIC pointers there. Each pointer is 3 bytes long, and starts // with an 0xFF which is correct, it says that it is a generic pointer to code memory. // memcpy(treatments,treatment_tbl,sizeof(treatments)); // this works just fine // // This however fails. It indexes treatments by 2 bytes, rather than 3 bytes, so it gets bogus pointers into current // treatment // current_treatment is GENERIC pointer. So indexing into an array of generic pointers and assigning one to // current_treatment SHOULD index by 3's and put the entire pointer there. current_treatment=treatments[current_mode]; }
struct example { unsigned char * name[10]; unsigned int flags; }; code struct example case1= { "123456789", 0xFEED };
I'm afraid this code is too buggy to demonstrate much of anything. The struct declaration has an array of 10 pointers to unsigned chars, while the initializer is one array of 10 (implicitly const) chars. That just doesn't match up.
And you didn't really want 0xFEED to be the initializer for the second char pointer in the array, did you?
This pointer
idata struct treatment_table code * current_treatment;
says that there is a pointer to CODE located in idata space.
Care informing us where the documentation says so?
The trouble is that in my original code example, an array is created of generic pointers,
No. Not only according to the compiler manual, but also by your own arguments, this:
struct treatment_table xdata * treatments[]=
is not an array of generic pointers. It's an array of pointers to xdata.
still no joy. The array is still not an array of generic pointers.
That's not surprising as your declarations are memory specific. You have declared a pointer to xdata residing in xdata and a pointer to code residing in xdata.
I suggest you (re)read the section in the manual that covers this, it explains it quite clearly.