This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

generic pointers and bad code problem

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];

}

Parents
  • 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.

Reply
  • 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.

Children
  • 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?

  • 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.

    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.

  • 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.

    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.