• AVR Freaks

Hot!I need a 2-byte pointer; right now I get 3-byte pointers only [KIND OF SOLVED]

Author
danw
Starting Member
  • Total Posts : 44
  • Reward points : 0
  • Joined: 2008/09/03 12:48:47
  • Location: 0
  • Status: offline
2019/04/12 17:59:34 (permalink)
0

I need a 2-byte pointer; right now I get 3-byte pointers only [KIND OF SOLVED]

Writing code using MPLAB v5.05, XC8 v2.00, for 18F47K42 (8k RAM).
I have the following macro to declare integer types that cannot be assigned to each other:
#define \
  decl_sint_type( tname, UN, minval, maxval ) \
typedef union \
{ \
    __ram int8_t  (* foo)[UN]; \
    int val; \
} tname; \
typedef int8_t tname##_min[minval]; \
typedef int8_t tname##_max[maxval]; \
void tname##_from_int( tname*, int ); \
void tname##_inc( tname* ); \
void tname##_dec( tname* ); \
bool tname##_invariant( tname const * )

sint stands for "strong int"
UN stands for "Unique Number"
So the macro declares a union of a pointer named "foo", to an array of chars of size UN, and an integer, "var".
foo is never used;  its purpose is to make assignments between types with different UN's incompatible, so as to resemble the type safety of C++.
decl_sint_type( wday_t , 42, 1, 7 );
decl_sint_type( month_t , 77, 1, 12 );
  wday_t wd;
  month_t mo;
  .........................
  wd = m; //compiler catches it, says "incompatible types"
  m = wd; //same thing

Only the second member of the union is used, to store an integer value.
The code works, but the size of this type is 3 bytes instead of 2.  I need 2-byte-ness.
Note the __ram qualifier.  My configuration file has address qualifiers as 'require'.
2 bytes should be enough for 8k of RAM;  I don't understand why I get 3-byte size...
I tried changing the first member to
    __eeprom  int8_t (* foo)[UN];

but the size is still 3 bytes.
I tried the qualifier inside the parenthesis, such as,
    int8_t (__ram * foo)[UN];

but that doesn't compile.  The XC8 manual is kind of vague on pointer sizes.
And there doesn't seem to be anything near a "near" qualifier.
I need the size to be 2-bytes, as I'm almost at the 8k limit and the program is not
finished, and 3-byters ruin some of my nicely aligned structures, from 16 bytes to 19.
 
EDIT:
I tried this:
#define \
  decl_sint_type( tname, UN, minval, maxval ) \
  typedef int8_t tname##_foo_t[UN]; \
  typedef __eeprom tname##_foo_t * tname##_pft; \
typedef union \
{ \
    tname##_pft foo; \
    int val; \
} tname; \
typedef int8_t tname##_min[minval]; \
typedef int8_t tname##_max[maxval]; \
void tname##_from_int( tname*, int ); \
void tname##_inc( tname* ); \
void tname##_dec( tname* ); \
bool tname##_invariant( tname const * )

but I get the same result;  3-byte size.
post edited by danw - 2019/04/13 10:46:57
#1

12 Replies Related Threads

    NKurzman
    A Guy on the Net
    • Total Posts : 17247
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/12 20:19:57 (permalink)
    +1 (1)
    Are you using 3 byte Pointers?  A Pointer can vary form between 1 and 3 bytes depending on the Use.  It can even change in size if it the Optimizer thinks it is a good idea.
    a 3 byte pointer will be able to point to RAM or Flash?  Are you using the Pointer that way?
    If you are trying to be clever with the Pointers the compiler will be forced to use 3 bytes.
    a const pointer will only Point to Flash so it will be 2 bytes.  I am Not sure how to force a RAM Only pointer.
     
    It sounds like you are trying to code an 8 bit PIC like you would a Desktop.
    #2
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11143
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/12 21:40:43 (permalink)
    +1 (1)
    Your PIC has 128K flash, so it will use 3-byte pointers for flash; I don't know if that influences the size of pointers to RAM.  Try compiling for a 18F46K42 and see if that changes anything.
    #3
    JPortici
    Super Member
    • Total Posts : 668
    • Reward points : 0
    • Joined: 2012/11/17 06:27:45
    • Location: Grappaland
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/13 00:16:53 (permalink)
    +1 (1)
    aha! I've been investigating this. And of course no confirmation from THAT guy at microchip support. THAT GUY just rewrote what i wrote without confirming or denying.
     
    Anyhow, i've stumbled upon this while porting my dsPIC bootloader to PIC18F K42.. in the K42 a pointer to flash memory using __rom qualifier will be 2 or 3 bytes wide depending on the amount of program memory available on the PIC.. in the 26K42 is 2 bytes (64k), in the 27K42 (128k) is 3 bytes.
     
    This was annoying to be because i wanted to be able to reach configuration space which is implemented at higher addresses... and since eeprom is also at higher addresses apparently a pointer to __eeprom is always 3 bytes wide.
     
    pointer to const will always be 3 bytes wide and they can access the whole program memory space
    #4
    danw
    Starting Member
    • Total Posts : 44
    • Reward points : 0
    • Joined: 2008/09/03 12:48:47
    • Location: 0
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/13 08:43:32 (permalink)
    0
    NKurzman
    Are you using 3 byte Pointers?  A Pointer can vary form between 1 and 3 bytes depending on the Use.  It can even change in size if it the Optimizer thinks it is a good idea.
    a 3 byte pointer will be able to point to RAM or Flash?  Are you using the Pointer that way?
    If you are trying to be clever with the Pointers the compiler will be forced to use 3 bytes.
    a const pointer will only Point to Flash so it will be 2 bytes.  I am Not sure how to force a RAM Only pointer.
     
    It sounds like you are trying to code an 8 bit PIC like you would a Desktop.


    Kurzman, I've never tried to have 2-byte pointers in desktops.  Perhaps it's possible, but I never needed them.  I've been programming PIC controllers since the early days of Microchip,  12C this or that's, in assembler.  The problem is that compilers were invented, and apparently they can't be un-invented.
    To your first question:  I am NOT "using" this pointer.  At all.  Never initialized.  Never read.  The purpose of its presence in the union is to make copying an object of one struct to another be rejected by the compiler.
    In C programming, you can write,
    typedef int weekday_t;
     
    typedef int month_t;
     
    weekday_t wd;
     
    month_t mo;
     
    ..............
     
    wd = mo; //month assigned to weekday --nonsense
     
    mo == wd; //month and weekday being compared --nonsense
     
    //etc.

    In C++ you make them different types, and that won't be allowed.
    In C, the compiler will accept that.
    But by using a union of an int and a pointer to an array, and making the arrays different sizes, I get assignment between wd and mo trigger a compiler error.  (See example of use in my original post.)
    Number 2:  I do understand how a pointer to flash needs to be 3-bytes, in this chip;  I just don't understand how a pointer to RAM needs to be 3 bytes.  My question is, is there a way to persuade the compiler to make this pointer just 2-bytes?
     
    jtemplesTry compiling for a 18F46K42 and see if that changes anything.

    I might try that just out of curiosity.  1/2 the ram and 1/2 the rom...  But that should reduce the pointer length needs by only 1 bit.  2 bytes for ram should suffice for even 64k of ram.  Even supposing the two bytes are used differently, like in some paged mode, the memory structure in the 47K42 is, according to the spec, 64 pages of 256 bytes.  So, that's 6 bits for page selection, on top of 8 bits of intra-page addressing.  I can't see why 3 bytes are needed.
     
    JPorticiaha! I've been investigating this. And of course no confirmation from THAT guy at microchip support. THAT GUY just rewrote what i wrote without confirming or denying.
     
    Anyhow, i've stumbled upon this while porting my dsPIC bootloader to PIC18F K42.. in the K42 a pointer to flash memory using __rom qualifier will be 2 or 3 bytes wide depending on the amount of program memory available on the PIC.. in the 26K42 is 2 bytes (64k), in the 27K42 (128k) is 3 bytes.

    Thanks for the confirmation.  Glad I'm not alone, at least.
    I didn't know that EEPROM was remapped to higher addresses;  I assumed it was on a separate address space.
    Good to know.
    I still don't understand why my pointer continues to be 3-bytes, even after qualifying it __ram.
     
    post edited by danw - 2019/04/13 08:55:10
    #5
    NKurzman
    A Guy on the Net
    • Total Posts : 17247
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/13 09:10:25 (permalink)
    +1 (1)
    What I mean is you keep referring to C++
    And Type Safety in a PIC18.
    If you can force the compiler to do, it will it affect code size or speed?
    What you are trying to do will work on a PIC24. Or you can run C++ on a small PIC32MM or MX. Or many of the Atmel Chips.
    #6
    aschen0866
    Super Member
    • Total Posts : 4423
    • Reward points : 0
    • Joined: 2006/01/08 22:18:32
    • Location: San Diego
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/13 09:49:33 (permalink)
    +3 (3)
    danw
    ...
    But by using a union of an int and a pointer to an array, and making the arrays different sizes, I get assignment between wd and mo trigger a compiler error. 
    ...

    I understand what you want to achieve but I don't understand why you need pointer. Can you do this:

    typedef struct {int weekday;} weekday_t;
    typedef struct {int month;} month_t;
    weekday_t wd;
    month_t mo;

    In this case, if you do wd = mo, the compiler will issue "error: (182) illegal conversion between types". 
    #7
    danw
    Starting Member
    • Total Posts : 44
    • Reward points : 0
    • Joined: 2008/09/03 12:48:47
    • Location: 0
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/13 10:46:03 (permalink)
    +1 (1)
    aschen0866
    danw
    ...
    But by using a union of an int and a pointer to an array, and making the arrays different sizes, I get assignment between wd and mo trigger a compiler error. 
    ...

    I understand what you want to achieve but I don't understand why you need pointer. Can you do this:

     
     
     
    typedef struct {int weekday;} weekday_t;
    typedef struct {int month;} month_t;
     
     
     
    weekday_t wd;
    month_t mo;
     
     
     

    In this case, if you do wd = mo, the compiler will issue "error: (182) illegal conversion between types". 


    Wow!  If you're right. this solves my problem...
    IT WORKS!
    Thank you!
    I feel so foolish now.  To my defence, I had read about this technique of mixing an integer and a pointer (to make enumerated types and integers assignment-incompatible) many years ago.  I think it was in Dr Dobb's journal.  But I don't have the issue anymore, so I can't take another look at it.  Perhaps it was meant to cure a different problem.
     
    EDIT: I re-titled the thread to add "[KIND OF SOLVED]", as my particular need is now met, but the problem of the compiler producing 3-byte pointers where they should be 2-byte pointers remains a concern.
    post edited by danw - 2019/04/13 10:49:30
    #8
    aschen0866
    Super Member
    • Total Posts : 4423
    • Reward points : 0
    • Joined: 2006/01/08 22:18:32
    • Location: San Diego
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/13 18:00:59 (permalink)
    +2 (2)
    danw
    ... but the problem of the compiler producing 3-byte pointers where they should be 2-byte pointers remains a concern.


    I think the problem is related to union, for example,

    union
    {
       int8_t *ptr;
    } test;
    ...
    printf("size of union %u\n", sizeof test);
    printf("size of pointer %u\n", sizeof test.ptr);

    and you get:

    size of union 3
    size of pointer 2

    #9
    danw
    Starting Member
    • Total Posts : 44
    • Reward points : 0
    • Joined: 2008/09/03 12:48:47
    • Location: 0
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/24 18:37:41 (permalink)
    0
    Ahhhhh,  thanks;   good to know.
    I wonder why it does that.  Doesn't seem to inflate an int.  I'm tempted to call it a bug.
     
    #10
    aschen0866
    Super Member
    • Total Posts : 4423
    • Reward points : 0
    • Joined: 2006/01/08 22:18:32
    • Location: San Diego
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/25 10:47:19 (permalink)
    +3 (3)
    danw
    ...  I'm tempted to call it a bug.

    Strictly speaking, the ANSI C Standard only requires the size of a union to be "sufficient to contain the largest of its members".
    #11
    mlp
    boots too small
    • Total Posts : 738
    • Reward points : 0
    • Joined: 2012/09/10 15:12:07
    • Location: previously Microchip XC8 team
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/26 14:18:44 (permalink)
    +1 (1)
    aschen0866
    Strictly speaking, the ANSI C Standard

    And also the subsequently issued C language standards, beginning with the first version of the ISO C standard, issued in 1990.

    Mark (this opinion available for hire)
    #12
    JPortici
    Super Member
    • Total Posts : 668
    • Reward points : 0
    • Joined: 2012/11/17 06:27:45
    • Location: Grappaland
    • Status: offline
    Re: I need a 2-byte pointer; right now I get 3-byte pointers only 2019/04/27 23:58:27 (permalink)
    +1 (1)
    danwI didn't know that EEPROM was remapped to higher addresses;  I assumed it was on a separate address space.



    it's all in the device datasheet :)
    I am also interested in why the union is three bytes and the containing pointer is one byte.
    Besides the probably wasted byte, it could lead to pretty nasty bugs... you declare a new type which is an union of a struct/bitfield and the corresponding array of bytes, you make a second type which is an union of an array of the previous type and the (supposed) corresponding array of bytes, the alignment goes down the toilet..
    #13
    Jump to:
    © 2019 APG vNext Commercial Version 4.5