Проблема вызова в PIC C18, искажены параметры - возможно, с помощью указателей на структуры? - PullRequest
2 голосов
/ 24 августа 2011

Я пытаюсь сделать довольно простой вызов, используя PICC18.

Используя симулятор MPLAB Я вижу, что аргументы, даже при входе в функцию, полностью искажены.

У меня естьследующий 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;

(Мой список TODO включает в себя разработку порядка, в котором мне нужно указать битовые поля)

Это встроено в дальнейшую структуру

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;

ивыделено где-то в выгружаемом ОЗУ (в main.c)

#pragma udata   
static t_aprsPacket s_packet;

Метод, определенный в aprs.h

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

(я попытался поместить туда "far" после следующей строки.Пример h. Никакого эффекта - и на этом PIC у меня нет 64K, так что действительно следует перекомпилировать все как 'near')

Реализация в aprs.c:

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

(Это может быть оптимизировано. Лучше, чтобы сначала это работало. Эта реализация позволяет мне видеть, что находится в ch, когда он идет по кругу.)

Пару вызовов из main () в main.c:

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");

Это приведение к (без знака) тоже не помогло.

ПервыйПовторные строки компилируются, но при запуске в имитаторе MPLAB приводят тарабарщины в аргументах реализации функции.

Строка strcpy выдает предупреждение компилятора «Предупреждение [2066] несоответствие квалификатора типа в присваивании».Было бы хорошо, если бы он сказал мне, какое задание.

Что я здесь не так сделал?

Спасибо

  • Ричард

1 Ответ

3 голосов
/ 24 августа 2011

Я вызывал процедуру инициализации ассемблера, которая использовала FSR2, поэтому испортил стек C.Я изменил его, чтобы использовать вместо него FSR0, и теперь он работает.

Более короткий код, который делает то же самое:

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

Я компилирую в режиме «отладки», поэтому не оптимизирую.Полезно посмотреть, как это происходит в этом режиме, поскольку у меня есть только ознакомительная версия компилятора.Новые версии экономят 66 местоположений программ и 3 байта оперативной памяти.Это также учит меня, что правильный путь для битовых полей -

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

Я принимаю оператор << как не включающий перенос. </p>

Спасибо - Ричард

(я быпометьте этот вопрос для удаления - но обратите внимание, что он был отмечен как любимый, поэтому не хотите выметать его из-под ног)

...