Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start of updating CAN ID header format to match v1.0 #99

Merged
merged 3 commits into from
Mar 28, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@
# CMake build directory
build/
cmake-build-*/
CMakeFiles/
cmake_install.cmake
CMakeCache.txt
Makefile
demo
run_tests
pavel-kirienko marked this conversation as resolved.
Show resolved Hide resolved

# IDE and tools
.idea
Expand All @@ -49,3 +55,6 @@ dsdlc_generated/

# Pycache
__pycache__/

# Ignore IDE folders
.vscode/
4 changes: 2 additions & 2 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ Note that the proposed API does not make any assumptions about the CAN driver in
A rough draft of the API definitions is provided below:

```c
#define CANARD_BROADCAST_NODE_ID 0
#define CANARD_MIN_NODE_ID 1
#define CANARD_BROADCAST_NODE_ID 255
#define CANARD_MIN_NODE_ID 0
#define CANARD_MAX_NODE_ID 127

#define CANARD_MEM_BLOCK_SIZE 32
Expand Down
59 changes: 23 additions & 36 deletions canard.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,17 @@
#define TRANSFER_TIMEOUT_USEC 2000000

#define TRANSFER_ID_BIT_LEN 5U
#define ANON_MSG_DATA_TYPE_ID_BIT_LEN 2U

#define SOURCE_ID_FROM_ID(x) ((uint8_t) (((x) >> 0U) & 0x7FU))
#define SERVICE_NOT_MSG_FROM_ID(x) ((bool) (((x) >> 7U) & 0x1U))
#define REQUEST_NOT_RESPONSE_FROM_ID(x) ((bool) (((x) >> 15U) & 0x1U))
#define SOURCE_ID_FROM_ID(x) ((uint8_t) (((x) >> 1U) & 0x7FU))
#define SERVICE_NOT_MSG_FROM_ID(x) ((bool) (((x) >> 25U) & 0x1U))
#define REQUEST_NOT_RESPONSE_FROM_ID(x) ((bool) (((x) >> 24U) & 0x1U))
#define DEST_ID_FROM_ID(x) ((uint8_t) (((x) >> 8U) & 0x7FU))
#define PRIORITY_FROM_ID(x) ((uint8_t) (((x) >> 24U) & 0x1FU))
#define MSG_TYPE_FROM_ID(x) ((uint16_t)(((x) >> 8U) & 0xFFFFU))
#define SRV_TYPE_FROM_ID(x) ((uint8_t) (((x) >> 16U) & 0xFFU))
#define PRIORITY_FROM_ID(x) ((uint8_t) (((x) >> 26U) & 0x1FU))
pavel-kirienko marked this conversation as resolved.
Show resolved Hide resolved
#define SUBJECT_TYPE_FROM_ID(x) ((uint16_t)(((x) >> 8U) & 0x7FFFU))
#define SRV_TYPE_FROM_ID(x) ((uint8_t) (((x) >> 15U) & 0x1FFU))

#define MAKE_TRANSFER_DESCRIPTOR(data_type_id, transfer_type, src_node_id, dst_node_id) \
(((uint32_t)(data_type_id)) | (((uint32_t)(transfer_type)) << 16U) | \
#define MAKE_TRANSFER_DESCRIPTOR(port_id, transfer_type, src_node_id, dst_node_id) \
pavel-kirienko marked this conversation as resolved.
Show resolved Hide resolved
(((uint32_t)(port_id)) | (((uint32_t)(transfer_type)) << 16U) | \
(((uint32_t)(src_node_id)) << 18U) | (((uint32_t)(dst_node_id)) << 25U))

#define TRANSFER_ID_FROM_TAIL_BYTE(x) ((uint8_t)((x) & 0x1FU))
Expand Down Expand Up @@ -110,20 +109,21 @@ void* canardGetUserReference(CanardInstance* ins)
return ins->user_reference;
}

void canardSetLocalNodeID(CanardInstance* ins, uint8_t self_node_id)
int16_t canardSetLocalNodeID(CanardInstance* ins, uint8_t self_node_id)
{
CANARD_ASSERT(ins != NULL);

if ((ins->node_id == CANARD_BROADCAST_NODE_ID) &&
(self_node_id >= CANARD_MIN_NODE_ID) &&
pavel-kirienko marked this conversation as resolved.
Show resolved Hide resolved
(self_node_id <= CANARD_MAX_NODE_ID))
{
ins->node_id = self_node_id;
}
else
{
CANARD_ASSERT(false);
return - CANARD_ERROR_INVALID_ARGUMENT;
}

return CANARD_OK;
}

uint8_t canardGetLocalNodeID(const CanardInstance* ins)
Expand Down Expand Up @@ -151,29 +151,20 @@ int16_t canardBroadcast(CanardInstance* ins,
uint32_t can_id = 0;
uint16_t crc = 0xFFFFU;

if (canardGetLocalNodeID(ins) == 0)
can_id = ((uint32_t) priority << 26U) | ((uint32_t) data_type_id << 8U) | ((uint32_t) canardGetLocalNodeID(ins) << 1U);
pavel-kirienko marked this conversation as resolved.
Show resolved Hide resolved

if (canardGetLocalNodeID(ins) == CANARD_BROADCAST_NODE_ID) // Anonymous message transfer
{
if (payload_len > 7)
{
return -CANARD_ERROR_NODE_ID_NOT_SET;
}

static const uint16_t DTIDMask = (1U << ANON_MSG_DATA_TYPE_ID_BIT_LEN) - 1U;

if ((data_type_id & DTIDMask) != data_type_id)
{
return -CANARD_ERROR_INVALID_ARGUMENT;
}

// anonymous transfer, random discriminator
const uint16_t discriminator = (uint16_t)((crcAdd(0xFFFFU, payload, payload_len)) & 0x7FFEU);
can_id = ((uint32_t) priority << 24U) | ((uint32_t) discriminator << 9U) |
((uint32_t) (data_type_id & DTIDMask) << 8U) | (uint32_t) canardGetLocalNodeID(ins);
uint8_t pseudo_id = crcAdd(0xFFFFU, payload, payload_len) & 0x7FU;
can_id |= (1U << 24U) | ((uint32_t) pseudo_id << 1U);
pavel-kirienko marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
can_id = ((uint32_t) priority << 24U) | ((uint32_t) data_type_id << 8U) | (uint32_t) canardGetLocalNodeID(ins);

if (payload_len > 7)
{
crc = crcAddSignature(crc, data_type_signature);
Expand Down Expand Up @@ -206,14 +197,15 @@ int16_t canardRequestOrRespond(CanardInstance* ins,
{
return -CANARD_ERROR_INVALID_ARGUMENT;
}
if (canardGetLocalNodeID(ins) == 0)
if (canardGetLocalNodeID(ins) == CANARD_BROADCAST_NODE_ID)
{
// Service transfer not supported for anonymous nodes
return -CANARD_ERROR_NODE_ID_NOT_SET;
}
pavel-kirienko marked this conversation as resolved.
Show resolved Hide resolved

const uint32_t can_id = ((uint32_t) priority << 24U) | ((uint32_t) data_type_id << 16U) |
((uint32_t) kind << 15U) | ((uint32_t) destination_node_id << 8U) |
(1U << 7U) | (uint32_t) canardGetLocalNodeID(ins);
const uint32_t can_id = ((uint32_t) priority << 26U) | ((uint32_t) data_type_id << 15U) |
((uint32_t) kind << 24U) | ((uint32_t) destination_node_id << 8U) |
(1U << 25U) | ((uint32_t) canardGetLocalNodeID(ins) << 1U);
uint16_t crc = 0xFFFFU;

if (payload_len > 7)
Expand Down Expand Up @@ -1081,12 +1073,7 @@ CANARD_INTERNAL uint16_t extractDataType(uint32_t id)
{
if (extractTransferType(id) == CanardTransferTypeBroadcast)
{
uint16_t dtid = MSG_TYPE_FROM_ID(id);
if (SOURCE_ID_FROM_ID(id) == CANARD_BROADCAST_NODE_ID)
{
dtid &= (1U << ANON_MSG_DATA_TYPE_ID_BIT_LEN) - 1U;
}
return dtid;
return (uint16_t) SUBJECT_TYPE_FROM_ID(id);
}
else
{
Expand Down
8 changes: 5 additions & 3 deletions canard.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ extern "C" {
#define CANARD_CAN_FRAME_MAX_DATA_LEN 8U

/// Node ID values. Refer to the specification for more info.
#define CANARD_BROADCAST_NODE_ID 0
#define CANARD_MIN_NODE_ID 1
#define CANARD_BROADCAST_NODE_ID 255
#define CANARD_MIN_NODE_ID 0
#define CANARD_MAX_NODE_ID 127

/// Refer to the type CanardRxTransfer
Expand Down Expand Up @@ -346,8 +346,10 @@ void* canardGetUserReference(CanardInstance* ins);
/**
* Assigns a new node ID value to the current node.
* Node ID can be assigned only once.
*
* Returns CANARD_OK if success, or negative error code if node ID is outside valid range.
pavel-kirienko marked this conversation as resolved.
Show resolved Hide resolved
*/
void canardSetLocalNodeID(CanardInstance* ins,
int16_t canardSetLocalNodeID(CanardInstance* ins,
uint8_t self_node_id);
pavel-kirienko marked this conversation as resolved.
Show resolved Hide resolved

/**
pavel-kirienko marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
53 changes: 26 additions & 27 deletions tests/test_rxerr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,35 +26,34 @@
#include <canard.h>

//Independent implementation of ID layout from https://uavcan.org/Specification/4._CAN_bus_transport_layer/
#define CONSTRUCT_PRIO(prio) (((prio) & 0x1F) << 24)
#define CONSTRUCT_MTID(mtid) (((mtid) & 0xFFFF) << 8)
#define CONSTRUCT_SID(sid) (((sid) & 0x7F))
#define CONSTRUCT_DISC(disc) (((disc) & 0x3FFF) << 10)
#define CONSTRUCT_DISC_MTID(mtid) (((mtid) & 0x3) << 8)
#define CONSTRUCT_STID(stid) (((stid) & 0xFF) << 16)
#define CONSTRUCT_DID(did) (((did) & 0x7F) << 8)
#define CONSTRUCT_REQUEST(request) (((request) & 0x1) << 15)

#define CONSTRUCT_SNM_BIT (1 << 7)

#define CONSTRUCT_ANON_MSG_ID(prio, disc, mtid, sid) (CONSTRUCT_PRIO(prio) | \
CONSTRUCT_DISC_MTID(mtid) | \
CONSTRUCT_DISC(disc) | \
CONSTRUCT_SID(sid) \
#define CONSTRUCT_PRIO(prio) (((prio) & 0x7) << 26)
#define CONSTRUCT_SUBJECT_ID(subject_id) (((subject_id) & 0xFFFF) << 8)
#define CONSTRUCT_SOURCE_ID(source_id) (((source_id) & 0x7F) << 1)
#define CONSTRUCT_SERVICE_ID(service_id) (((service_id) & 0x1FF) << 15)
#define CONSTRUCT_DEST_ID(dest_id) (((dest_id) & 0x7F) << 8)
#define CONSTRUCT_REQUEST(request) (((request) & 0x1) << 24)

#define CONSTRUCT_ANON_BIT (1 << 24)
#define CONSTRUCT_SNM_BIT (1 << 25)
#define CONSTRUCT_PV_BIT (1)

#define CONSTRUCT_MSG_ID(prio, subject_id, source_id) (CONSTRUCT_PRIO(prio) | \
CONSTRUCT_SUBJECT_ID(subject_id) | \
CONSTRUCT_SOURCE_ID(source_id) | \
CONSTRUCT_PV_BIT |\
CANARD_CAN_FRAME_EFF)

#define CONSTRUCT_MSG_ID(prio, mtid, sid) (CONSTRUCT_PRIO(prio) | \
CONSTRUCT_MTID(mtid) | \
CONSTRUCT_SID(sid) | \
CANARD_CAN_FRAME_EFF)

#define CONSTRUCT_SVC_ID(prio, stid, request, did, sid) (CONSTRUCT_PRIO(prio) | \
CONSTRUCT_STID(stid) | \
CONSTRUCT_REQUEST(request) | \
CONSTRUCT_DID(did) | \
CONSTRUCT_SID(sid) | \
CONSTRUCT_SNM_BIT | \
CANARD_CAN_FRAME_EFF)
#define CONSTRUCT_ANON_MSG_ID(prio, subject_id, source_id) (CONSTRUCT_ANON_BIT | \
CONSTRUCT_MSG_ID(prio, subject_id, source_id))

#define CONSTRUCT_SVC_ID(prio, service_id, request, dest_id, source_id) (CONSTRUCT_PRIO(prio) | \
CONSTRUCT_SNM_BIT | \
CONSTRUCT_REQUEST(request) | \
CONSTRUCT_SERVICE_ID(service_id) | \
CONSTRUCT_DEST_ID(dest_id) | \
CONSTRUCT_SOURCE_ID(source_id) | \
CONSTRUCT_PV_BIT |\
CANARD_CAN_FRAME_EFF)

#define CONSTRUCT_START(start) (((start) & 0x1) << 7)
#define CONSTRUCT_END(end) (((end) & 0x1) << 6)
Expand Down