Wrong union tag size

I do not know if my topic below is related to Custom message signature fail
but, here I go:

I have a DSDL definition that looks like:
myDSDL.uavcan

@union
uint8 value1
uint8 value2
uint8 value3
uint8 value4

When compiled with libcanard dsdl_compiler, I can see in the _myDSDL_encode_internal(…) function that tag size is 3 bits, I expected 2…:

uint32_t test_MyDSDL_encode_internal(test_MyDSDL* source,
  void* msg_buf,
  uint32_t offset,
  uint8_t CANARD_MAYBE_UNUSED(root_item))
{
    // Max Union Tag Value
    CANARD_ASSERT(source->union_tag <= 3);

    // Union Tag 3 bits
    canardEncodeScalar(msg_buf, offset, 3, (void*)&source->union_tag); // 3 bits
    offset += 3;

    if (source->union_tag == 0) {
    canardEncodeScalar(msg_buf, offset, 8, (void*)&source->value1); // 255
    offset += 8;

    }
    else if (source->union_tag == 1) {
    canardEncodeScalar(msg_buf, offset, 8, (void*)&source->value2); // 255
    offset += 8;

    }
    else if (source->union_tag == 2) {
    canardEncodeScalar(msg_buf, offset, 8, (void*)&source->value3); // 255
    offset += 8;

    }
    else if (source->union_tag == 3) {
    canardEncodeScalar(msg_buf, offset, 8, (void*)&source->value4); // 255
    offset += 8;

    }

    return offset;
}

libuavcan compiler generates tag size = 2.

What is wrong?

Regards

The DSDL compiler in Libcanard was broken so we removed it. If you check the upstream, there is no compiler there. Please don’t use it.

If compiling libcanard for v0, what compiler shall I use?

If I am not completely wrong, is this the place were union is calculated?

In init.py:

    if t.kind == t.KIND_MESSAGE:
        t.has_array = inject_cpp_types(t.fields)
        t.has_float16 = has_float16(t.fields)
        inject_cpp_types(t.constants)
        t.all_attributes = t.fields + t.constants
        t.union = t.union and len(t.fields)
        if t.union:
            t.union = len(t.fields).bit_length()
    else:
        t.request_has_array = inject_cpp_types(t.request_fields)
        t.request_has_float16 = has_float16(t.request_fields)
        inject_cpp_types(t.request_constants)
        t.response_has_array = inject_cpp_types(t.response_fields)
        t.response_has_float16 = has_float16(t.response_fields)
        inject_cpp_types(t.response_constants)
        t.all_attributes = t.request_fields + t.request_constants + t.response_fields + t.response_constants
        t.request_union = t.request_union and len(t.request_fields)
        t.response_union = t.response_union and len(t.response_fields)
        if t.request_union:
            t.request_union = len(t.request_fields).bit_length()
        if t.response_union:
            t.response_union = len(t.response_fields).bit_length()

If so, to just fix my issue with wrong union tag size, can some of the above rows be changed to work properly?

Currently, there is no DSDL compiler for libcanard. We may develop one later for v1.

I suppose you should subtract one from len(...).bit_length().

Correct.
(len(...)-1).bit_length()
solved it.

1 Like