Search code examples
cmicrocontrollerpicpic18

Problem calling in PIC C18, parameters garbled - using pointers to structures perhaps?


I am trying to make a fairly simple call using PICC18.

Using the MPLAB simulator I am seeing the arguments, even on entry to the function, being completely garbled.

I have the following typedef

typedef struct
{
    //  t_ax25AddressChar callsign[6];
    unsigned char callsign[6];
    union
    {
        struct
        {
            unsigned isRepeated:1; // MSB - 1=repeated
            unsigned reserved:2; // Reserved
            unsigned ssid:4; // SSID
            unsigned isLast:1; // LSB - Is the last address
        };
        unsigned char value;
    } flags;
} t_ax25Callsign;

(My TODO list includes working out the order I need to specify bitfields)

That is embedded in a further struct

typedef struct
{
    union
    {
        struct
        {
            t_ax25Callsign to;
            t_ax25Callsign from;
            t_ax25Callsign path[APRS_MAX_REPEATERS];
        };
        t_ax25Callsign allCallsigns[APRS_MAX_REPEATERS + 2];
    } address;
    // PID and Control are hard coded for APRS
    const char message[APRS_MAX_MESSAGE_LENGTH + 1]; // null terminated message string
} t_aprsPacket;

and allocated somewhere in paged RAM (in main.c)

#pragma udata   
static t_aprsPacket s_packet;

The method defined in aprs.h

extern void aprsMakeCallsignPgm(t_ax25Callsign *buffer,
                                const rom char *callsign, unsigned char ssid);

(I did try putting a "far" in there following string.h's example. No effect - and on this PIC I don't have 64K so really ought to recompile everything as 'near')

The implementation in aprs.c is

void aprsMakeCallsignPgm(t_ax25Callsign *buffer,
                     const rom char *callsign,
                     unsigned char ssid)
{
    int i = 0;
    volatile char ch;
    for(i=0; i<6 && (ch = callsign[i]) != 0; i++)
    {
        buffer->callsign[i] = ch << 1;
    }
    for(   ; i<6; i++)
    {
        buffer->callsign[i] = (' '<<1);
    }

    buffer->flags.value = 0;
    buffer->flags.ssid = ssid;
}

(It could be optimised. Best get this working first. This implementation lets me see what's in ch as it goes round the loop.)

A couple of calls from main() in main.c are

aprsMakeCallsignPgm(&(s_packet.address.from), "M0RJC", (unsigned char)9);
aprsMakeCallsignPgm(&(s_packet.address.to), "APRS", 0);
s_packet.address.to.flags.isLast = 1;
strcpypgm2ram(s_packet.message, "Hard coded test message");

That cast to (unsigned char) didn't help either.

The first three lines compile, but when run in the MPLAB simulator produce gibberish in the arguments in the function implementation.

The strcpy line gives a compiler warning "Warning [2066] type qualifier mismatch in assignment". It would be nice if it told me which assignment.

What have I done wrong here?

Thanks

  • Richard

Solution

  • I was calling an assembler init routine which was using FSR2, so corrupting the C stack. I changed it to use FSR0 instead and it now works.

    The shorter code that does the same thing is

    void aprsMakeCallsignPgm(t_ax25Callsign *buffer,
                             const rom char *callsign,
                             unsigned char ssid)
    {
        int i; 
        overlay char *dst = buffer->callsign;
        for(i = 6; i && (*dst++ = (*callsign++ << 1)); i--);
        dst--; // Rewind that 0. Good job flags is there to save from overrun
        for(   ; i ; i--) *dst++ = (' '<<1);
    
        buffer->flags.value = (ssid & 0x0F) << 1;
    }
    

    I'm compiling in "debug" mode, so not optimising. It's useful to see how it does in this mode as I only have the evaluation version of the compiler. The new versions saves 66 program locations and 3 bytes of RAM. It also teaches me that the correct way round for bitfields is

       struct
        {
            unsigned isLast:1;     // LSB - Is the last address
            unsigned ssid:4;       // SSID
            unsigned reserved:2;   // Reserved
            unsigned isRepeated:1; // MSB - 1=repeated
        };
    

    I take the << operator as not including carry.

    Thanks - Richard

    (I would mark this question for remove - but note it has been marked a favourite so don't want to sweep it from underneath someone's feet)