Проблема с вызовом в PIC C18, параметры искажены - возможно, с использованием указателей на структуры?

Я пытаюсь сделать довольно простой вызов, используя 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);

(Я попытался поставить туда «далеко», следуя примеру string.h. Никакого эффекта - и на этом PIC у меня нет 64 КБ, поэтому действительно нужно перекомпилировать все как «рядом»)

Реализация в 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");

Это приведение к (unsigned char) тоже не помогло.

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

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

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

Спасибо

  • Ричард

person Richard Corfield    schedule 23.08.2011    source источник
comment
У меня есть вызов ассемблера выше main.c. Если я прокомментирую это, все сработает, поэтому мне нужно посмотреть там.   -  person Richard Corfield    schedule 24.08.2011


Ответы (1)


Я вызывал подпрограмму инициализации ассемблера, которая использовала 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
    };

Я беру оператор ‹‹ без переноса.

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

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

person Richard Corfield    schedule 23.08.2011
comment
Как мы видим, при использовании ассемблера или C ошибка в любой части вашей программы может повлиять на любую другую часть! - person David Grayson; 24.08.2011
comment
Сборка предшествовала моему решению начать использовать C. Использование C означает гораздо более быструю разработку, но такие маленькие подводные камни, как FSR, легко пропустить. Я думаю, что C здесь может быть не без ловушек. - person Richard Corfield; 24.08.2011