0

組み込みシステム(リトルエンディアンARM、言語C-ここでテスト目的でC ++を使用している場合でも)の場合、添付のコードを記述しました。ビットアラインされ、指定されたビット長のさまざまな構成データを送受信する必要があります。構成は、次のように送受信する必要のある変数ごとにfield_conf_tを使用して実行されます。

typedef struct field_conf_t { ... }; // see below

typedef struct {
    field_conf_t    a;
    field_conf_t    b;
    field_conf_t    c;
} tx_fields_conf_t;

const tx_fields_conf_t tx_fields_conf = {
    { 0, 8  },      // a - offset/length
    { 28, 12 },     // b - offset/length
    { 56, 8  }      // c - offset/length
};

私が抱えている問題は、単一のビット操作について多くのことを考えていることです。テストは失敗します。

ここにコードがあります:

#include <stdint.h>

#define BOOST_TEST_MODULE BitFieldTest
#include <boost/test/unit_test.hpp>

typedef uint8_t     uint8;
typedef uint16_t    uint16;
typedef uint32_t    uint32;
typedef unsigned long long uint64;

typedef struct {
    uint8   offset;     // [0-63]
    uint8   length;     // [1-32]
} field_conf_t;

typedef struct {
    field_conf_t    a;
    field_conf_t    b;
    field_conf_t    c;
} tx_fields_conf_t;

typedef union {
    uint8   buf[8];
    uint64  contents;
} msg_t;

void set_value(msg_t* const msg, const field_conf_t* const field, uint32 value)
{
    const uint32 mask = (1 << field->length) - 1;
    msg->contents    &= ~(mask          << field->offset);  // clear old contens
    msg->contents    |=  (value & mask) << field->offset;   // set new contens
}

uint32 get_value(const msg_t* const msg, const field_conf_t* const field)
{
    const uint32 mask = (1 << field->length) - 1;

    uint64 value = (msg->contents >> field->offset);
    value       &= mask;

    return (uint32)value;
}

// ########################################################################
struct TestFixture {
    TestFixture() : a(0xAA), b(0xBBB), c(0xCC) {
        conf.a.offset =  0; conf.a.length = 8;
        conf.b.offset = 25; conf.b.length = 12;
        conf.c.offset = 56; conf.a.length = 8;
    }
    uint32 a, b, c;
    msg_t msg;
    tx_fields_conf_t conf;
};

BOOST_FIXTURE_TEST_SUITE(MsgBitfieldTest, TestFixture);

BOOST_AUTO_TEST_CASE(Test_01)
{
    set_value(&msg, &conf.a, a);
    BOOST_CHECK(get_value(&msg, &conf.a) == a);

    set_value(&msg, &conf.b, b);
    BOOST_CHECK(get_value(&msg, &conf.a) == a);
    BOOST_CHECK(get_value(&msg, &conf.b) == b);

    set_value(&msg, &conf.c, c);
    BOOST_CHECK(get_value(&msg, &conf.a) == a);
    BOOST_CHECK(get_value(&msg, &conf.b) == b);
    BOOST_CHECK(get_value(&msg, &conf.c) == c);
}

BOOST_AUTO_TEST_SUITE_END();

およびテスト実行出力

Running 1 test case...
d:/work/bugee/test/can_msg/msg_bitsfields/msg_bitsfields/main.cpp(65): error in
"Test_01": check get_value(&msg, &conf.b) == b failed
d:/work/bugee/test/can_msg/msg_bitsfields/msg_bitsfields/main.cpp(69): error in
"Test_01": check get_value(&msg, &conf.b) == b failed
d:/work/bugee/test/can_msg/msg_bitsfields/msg_bitsfields/main.cpp(70): error in
"Test_01": check get_value(&msg, &conf.c) == c failed

*** 3 failures detected in test suite "BitFieldTest"

バッファサイズは常に8バイトです。ここで64ビット長を使用できることを嬉しく思います。バイトアラインされた操作にも失敗する前に(各バイトのマスクとビット操作)。値はint32/uint32より大きくすることはできないことに注意してください。また、Cビットフィールドについても知っています。それらは遅すぎるので、使用する組み込みシステムの高速ソリューションが必要です(他の時間のかかるタスクがあります)。

lsb / msb 32ビットまたは8バイトスライス高速ソリューションのソリューションにも興味がありますが、コンパイラーにより、64ビットデータ型の使用はさらにパフォーマンスが高いと思います。

4

2 に答える 2

0

最初のコードブロックに次のような問題がありますか?

const tx_fields_conf_t tx_fields_conf = {
    { 0, 8  },      // a - offset/length
    { 28, 12 },     // b - offset/length -- note the 28 here as the offset
    { 56, 8  }      // c - offset/length
};

しかし、アプリケーションの後半では、次のようになります。

struct TestFixture {
    TestFixture() : a(0xAA), b(0xBBB), c(0xCC) {
        conf.a.offset =  0; conf.a.length = 8;
        conf.b.offset = 25; conf.b.length = 12;  // offset is *25* here, not 28 as above. Poss. problem?
        conf.c.offset = 56; conf.a.length = 8;
    }
    uint32 a, b, c;
    msg_t msg;
    tx_fields_conf_t conf;
};

重要な不一致である可能性はありますか?多分何もありませんが、私はそれに気づきました...私はそれを指摘すると思いました。

于 2012-08-28T13:17:14.273 に答える
0

問題は、set_value

const uint32 mask = (1 << field->length) - 1;
msg->contents    &= ~(mask          << field->offset);  // clear old contens
msg->contents    |=  (value & mask) << field->offset;   // set new contens

mask << field->offsetは 32 ビット値であるため、 のときにエッジからオーバーフローしますfield->offset + field->length >= 32。64 ビットに変更maskすると、ビット シフトが 64 ビット操作として実行されるようになります。

const uint64 mask = (1 << field->length) - 1;
于 2012-08-28T13:20:59.887 に答える