Понимание поведения макроса и протопотоков - PullRequest
0 голосов
/ 21 мая 2018

Заранее спасибо за помощь.

Сначала предисловие.Я смотрел на использование реализации Contiki TSCH, приведенной на https://github.com/contiki-os/contiki/tree/master/core/net/mac/tsch. Во время выполнения простого примера в симуляторе Cooja (с несколькими сообщениями журнала, которые я добавил в базовый код, чтобы я мог видеть, что происходит), язаметил, что счетчик ASN не увеличивал свой старший значащий байт.

В частности, ASN (абсолютный номер слота для TSCH) задается структурой

// data type of absolute slot number
struct tsch_asn_t {
  uint32_t ls4b; /* least significant 4 bytes */
  uint8_t  ms1b; /* most significant 1 byte */
};

и по существу может рассматриваться какв качестве значения индекса, представленного в виде двух переменных, старший значащий байт и младший значащий 4 байта.Следующий макрос используется для увеличения ASN на заданную величину.

// Here is the macro
#define TSCH_ASN_INC(asn, inc) do { \
    printf("TSCH INC1: new UNDEF, old %u, inc %u\n", (asn).ls4b, inc);  \
\
    uint32_t new_ls4b = (asn).ls4b + (inc); \
\
    printf("TSCH INC2: new %u, old %u, inc %u\n",new_ls4b, (asn).ls4b, inc);  \
\
    if(new_ls4b < (asn).ls4b) { (asn).ms1b++; } \
\
    printf("TSCH INC3: new %u, old %u, inc %u\n",new_ls4b, (asn).ls4b, inc);  \
\
    (asn).ls4b = new_ls4b; \
\
    printf("TSCH INC4: new %u, old %u, inc %u\n",new_ls4b, (asn).ls4b, inc);  \
} while(0);

На данный момент игнорируйте операторы printf (я добавил их, чтобы попытаться понять, что происходит).Как я понимаю этот макрос, то, что происходит, это то, что младшие байты сначала увеличиваются.Затем, если младшие значащие байты обертываются вокруг старшего значащего байта, то увеличивается.Просматривая журнал того, что происходило, я заметил, что старший значащий байт не увеличивается, когда младшие значащие байты обернуты вокруг.

Теперь к моему актуальному вопросу.Чтобы определить, почему самый значимый байт не был увеличен, я добавил вышеупомянутые операторы печати в макрос и добавил операторы печати выше и ниже фактического вызова макроса, как показано ниже (обратите внимание, что ASN задается tsch_current_asn, а timeslot_diff - это количество, которое я хочуувеличить ASN на).

printf("TSCH INC BEFORE: ms1b %u, ls4b %u, inc %u\n",tsch_current_asn.ms1b, tsch_current_asn.ls4b, timeslot_diff);
TSCH_ASN_INC(tsch_current_asn, timeslot_diff);
printf("TSCH INC AFTER: ms1b %u, ls4b %u, inc %u\n",tsch_current_asn.ms1b, tsch_current_asn.ls4b, timeslot_diff);

Выполнение этого привело к следующему журналу, который абсолютно меня озадачил

// LOG
TIME        DEVID   LOG MSG
00:28.885   ID:1    TSCH INC BEFORE: ms1b 0, ls4b 1877, inc 0
00:28.888   ID:1    TSCH INC1: new UNDEF, old 1877, inc 0
00:28.891   ID:1    TSCH INC2: new 1878, old 0, inc 1877
00:28.895   ID:1    TSCH INC3: new 1878, old 0, inc 1877
00:28.898   ID:1    TSCH INC4: new 1878, old 0, inc 1878
00:28.901   ID:1    TSCH INC AFTER: ms1b 0, ls4b 1878, inc 0

В частности, кажется, что между первым и вторым оператором printf вмакрос inc (timeslot_diff) изменился с 0 на 1877. Другими словами, мне кажется, что оператор

uint32_t new_ls4b = (asn).ls4b + (inc); \

изменил значение inc (timeslot_diff).Более того, мне кажется, что это утверждение меняет ans.ls4b (tsch_current_asn.ls4b) с 1877 на 0.

Имею ли я более высокий момент, чтобы говорить о том, как работают макросы, или это эффект прототоков Contiki?(т. е. приостановлено и позднее возобновлено)?

Для справки, фактический код для вызова макроса дан в строке 1035 из https://github.com/contiki-os/contiki/blob/master/core/net/mac/tsch/tsch-slot-operation.c, а макрос - в строке 67 из https://github.com/contiki-os/contiki/blob/master/core/net/mac/tsch/tsch-asn.h.

1 Ответ

0 голосов
/ 22 мая 2018

Похоже, что несоответствие между спецификаторами printf и фактическими типами аргументов происходит в 16-битной архитектуре.Рекомендуется использовать спецификаторы, определенные как макроконстанты формата в inttypes.h для всех целочисленных типов, приходящихся на stdint.h

Т.е. когда x имеет тип uint32_t, вы должны использовать

printf("x is %"PRIu32" \n", x);

вместо

printf("x is %u \n", x);
...