2012-08-28 4 views
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 비트 데이터 유형을 사용하는 것이 컴파일러로 인해 더 많은 성능을 제공한다고 가정합니다.

답변

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

중요한 차이의 모든 기회를? 아무 것도 아닐지도 모르지만 나는 그것을 지적했다.

+0

감사합니다, 그러나 이것은 문제가되지 않습니다 64 비트에 mask을 변경하면 64 비트 연산으로 수행 된 비트 변화를 얻기 위해 작동합니다. 최종 버전에서 사용하려는 구조 'API'. – user1630297

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 될 것이라는 것이다. 이 지적 않았다

const uint64 mask = (1 << field->length) - 1; 
+0

오 감사합니다; 그것은 문제를 해결합니다. – user1630297

관련 문제