Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
uavcan.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020 Freek van Tienen <freek.v.tienen@gmail.com>
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
27#include "uavcan.h"
28#include "mcu_periph/can.h"
30#include "uavcan.protocol.NodeStatus.h"
31#include "uavcan_reporting.h"
32#include "mcu_periph/sys_time.h"
34
35#ifndef UAVCAN_NODE_ID
36#define UAVCAN_NODE_ID 100
37#endif
38
39#ifndef UAVCAN_BAUDRATE
40#define UAVCAN_BAUDRATE 1000000
41#endif
42
44
45#if UAVCAN_USE_CAN1
46#ifndef UAVCAN_CAN1_NODE_ID
47#define UAVCAN_CAN1_NODE_ID UAVCAN_NODE_ID
48#endif
49
50#ifndef UAVCAN_CAN1_BAUDRATE
51#define UAVCAN_CAN1_BAUDRATE UAVCAN_BAUDRATE
52#endif
53
54struct uavcan_iface_t uavcan1 = {
55 .can_net = {.can_ifindex = 1},
56 .can_baudrate = UAVCAN_CAN1_BAUDRATE,
57 .node_id = UAVCAN_CAN1_NODE_ID,
58 .initialized = false
59};
60#endif
61
62#if UAVCAN_USE_CAN2
63#ifndef UAVCAN_CAN2_NODE_ID
64#define UAVCAN_CAN2_NODE_ID UAVCAN_NODE_ID
65#endif
66
67#ifndef UAVCAN_CAN2_BAUDRATE
68#define UAVCAN_CAN2_BAUDRATE UAVCAN_BAUDRATE
69#endif
70
71
72struct uavcan_iface_t uavcan2 = {
73 .can_net = {.can_ifindex = 2},
74 .can_baudrate = UAVCAN_CAN2_BAUDRATE,
75 .node_id = UAVCAN_CAN2_NODE_ID,
76 .initialized = false
77};
78#endif
79
80
81static void can_frame_cb(struct pprzcan_frame* rx_msg, UNUSED struct pprzaddr_can* src_addr, void* user_data) {
82 struct uavcan_iface_t *iface = (struct uavcan_iface_t *)user_data;
83
84 CanardCANFrame rx_frame = {0};
85 memcpy(rx_frame.data, rx_msg->data, 8);
86 rx_frame.data_len = rx_msg->len;
87 if (rx_msg->can_id & CAN_FRAME_EFF) {
88 rx_frame.id = CANARD_CAN_FRAME_EFF | (rx_msg->can_id & CAN_EID_MASK);
89 } else {
90 rx_frame.id = rx_msg->can_id & CAN_SID_MASK;
91 }
92
93 // Let canard handle the frame
94 canardHandleRxFrame(&iface->canard, &rx_frame, rx_msg->timestamp);
95}
96
97/*
98 * Transmitter thread.
99 */
100static void uavcan_tx(void* p)
101{
102 struct uavcan_iface_t *iface = (struct uavcan_iface_t *)p;
103 uint8_t err_cnt = 0;
104
105 while (true) {
106 // wait to be awaken
107 pprz_bsem_wait(&iface->bsem);
108
109 pprz_mtx_lock(&iface->tx_mutex);
110 for (const CanardCANFrame *txf = NULL; (txf = canardPeekTxQueue(&iface->canard)) != NULL;) {
111 struct pprzcan_frame tx_msg;
112 memcpy(tx_msg.data, txf->data, 8);
113 tx_msg.len = txf->data_len;
115
116 if (!can_transmit_frame(&tx_msg, &iface->can_net)) {
117 err_cnt = 0;
118 canardPopTxQueue(&iface->canard);
119 } else {
120 // After 5 retries giveup and clean full queue
121 if (err_cnt >= 5) {
122 err_cnt = 0;
123 while (canardPeekTxQueue(&iface->canard)) { canardPopTxQueue(&iface->canard); }
124 continue;
125 }
126
127 // Timeout - just exit and try again later
128 pprz_mtx_unlock(&iface->tx_mutex);
130 pprz_mtx_lock(&iface->tx_mutex);
131 continue;
132 }
133 }
134 pprz_mtx_unlock(&iface->tx_mutex);
135 }
136}
137
142{
143 struct uavcan_iface_t *iface = (struct uavcan_iface_t *)ins->user_reference;
144 // Go through all registered callbacks and call function callback if found
145 for (uavcan_event *ev = uavcan_event_hd; ev; ev = ev->next) {
146 if (transfer->data_type_id == ev->data_type_id) {
147 ev->cb(iface, transfer);
148 }
149 }
150}
151
157 uint16_t data_type_id,
160{
161
162 // Go through all registered callbacks and return signature if found
163 for (uavcan_event *ev = uavcan_event_hd; ev; ev = ev->next) {
164 if (data_type_id == ev->data_type_id) {
165 *out_data_type_signature = ev->data_type_signature;
166 return true;
167 }
168 }
169 return false;
170}
171
172
173
174#if CANARD_ALLOCATE_SEM
175
177 pprz_bsem_t* bsem = (pprz_bsem_t*)allocator->semaphore;
179}
180
182 pprz_bsem_t* bsem = (pprz_bsem_t*)allocator->semaphore;
184}
185
186#endif
187
188
192static void uavcanInitIface(struct uavcan_iface_t *iface)
193{
194 pprz_bsem_init(&iface->bsem, true);
195 pprz_mtx_init(&iface->tx_mutex);
196
199
200 // Initialize canard
201 canardInit(&iface->canard, iface->canard_memory_pool, sizeof(iface->canard_memory_pool),
203
204
205#if CANARD_ALLOCATE_SEM
206 // must be initialized after canardInit
207 pprz_bsem_init(&iface->allocator_bsem, false);
208 iface->canard.allocator.semaphore = &iface->allocator_bsem;
209#endif
210
211 // Update the uavcan node ID
212 canardSetLocalNodeID(&iface->canard, iface->node_id);
213
214 // Start the receiver and transmitter thread
215 can_register_callback(can_frame_cb, &iface->can_net, (void *)iface);
216
217 if(!pprz_thread_create(&iface->thread_tx, 2048, "uavcan_tx", PPRZ_NORMAL_PRIO +7, uavcan_tx, (void *)iface)) {
218 iface->initialized = true;
219 }
220}
221
225void uavcan_init(void)
226{
227#if UAVCAN_USE_CAN1
229#endif
230#if UAVCAN_USE_CAN2
232#endif
235}
236
240void uavcan_bind(uint16_t data_type_id, uint64_t data_type_signature, uavcan_event *ev, uavcan_callback cb)
241{
242 // Configure the event
243 ev->data_type_id = data_type_id;
244 ev->data_type_signature = data_type_signature;
245 ev->cb = cb;
247
248 // Switch the head
250}
251
253 uint32_t key = (destination_node_id << 24) | (iface->node_id <<16) | transfer->data_type_id;
255
256 if (transfer_id == NULL) {
257 // key does not exists yet
258 uint8_t zero = 0;
259 kv_set(&iface->transfer_ids_store, key, &zero);
260 }
261
262 return transfer_id;
263}
264
269{
270 if (!iface->initialized) { return; }
271 pprz_mtx_lock(&iface->tx_mutex);
272
273 transfer->transfer_type = CanardTransferTypeBroadcast;
274 transfer->inout_transfer_id = get_transfer_id(iface, 0, transfer);
275 if(canardBroadcastObj(&iface->canard, transfer) < 0) {
276 iface->nb_errors++;
277 }
278
279 pprz_mtx_unlock(&iface->tx_mutex);
280
281 // Wake Tx thread
282 pprz_bsem_signal(&iface->bsem);
283}
284
285
290{
291 if (!iface->initialized) { return; }
292 pprz_mtx_lock(&iface->tx_mutex);
293
294 transfer->transfer_type = CanardTransferTypeRequest;
295 transfer->inout_transfer_id = get_transfer_id(iface, destination_node_id, transfer);
297 iface->nb_errors++;
298 }
299
300 pprz_mtx_unlock(&iface->tx_mutex);
301
302 // Wake Tx thread
303 pprz_bsem_signal(&iface->bsem);
304}
305
306
307
308
313void uavcan_broadcast(struct uavcan_iface_t *iface, uint64_t data_type_signature, uint16_t data_type_id,
314 uint8_t priority, const void *payload,
315 uint16_t payload_len)
316{
319 transfer.data_type_signature = data_type_signature;
320 transfer.data_type_id = data_type_id;
321 transfer.priority = priority;
322 transfer.payload = payload;
323 transfer.payload_len = payload_len;
324
325 uavcan_transfer(iface, &transfer);
326}
327
328
333{
334 if (!iface->initialized) { return; }
335 pprz_mtx_lock(&iface->tx_mutex);
336
337 transfer->transfer_type = CanardTransferTypeResponse;
339
340 pprz_mtx_unlock(&iface->tx_mutex);
341
342 // Wake Tx thread
343 pprz_bsem_signal(&iface->bsem);
344}
struct abi_struct * next
Definition abi_common.h:71
abi_callback cb
Definition abi_common.h:70
int can_register_callback(can_rx_frame_callback_t callback, struct pprzaddr_can *src_addr, void *user_data)
Add a callback on received frames from an interface.
Definition can.c:88
uint8_t len
Definition can.h:74
int can_ifindex
Definition can.h:83
uint8_t data[SOCKETCAN_MAX_DLEN]
Definition can.h:77
socketcan_id_t can_id
Definition can.h:73
#define CAN_FRAME_EFF
Definition can.h:62
#define CAN_EID_MASK
Definition can.h:64
#define CAN_SID_MASK
Definition can.h:65
#define UNUSED(x)
int can_transmit_frame(struct pprzcan_frame *txframe, struct pprzaddr_can *addr)
Definition can_arch.c:152
void sys_time_msleep(uint32_t ms)
Sleep.
int pprz_mtx_unlock(pprz_mutex_t *mtx)
void pprz_bsem_init(pprz_bsem_t *bsem, bool taken)
int pprz_thread_create(pprz_thread_t *thread, size_t size, const char *name, uint8_t prio, void(*pf)(void *), void *arg)
Creates a new thread whose stack is dynamically allocated.
int pprz_mtx_init(pprz_mutex_t *mtx)
int pprz_mtx_lock(pprz_mutex_t *mtx)
void pprz_bsem_signal(pprz_bsem_t *bsem)
void pprz_bsem_wait(pprz_bsem_t *bsem)
#define PPRZ_NORMAL_PRIO
static float p[2][2]
int kv_set(kv_store_t *kv, uint32_t key, const void *value)
Sets a value for a given key.
Definition kv_store.c:79
void * kv_get(const kv_store_t *kv, uint32_t key)
Retrieves the value associated with a given key.
Definition kv_store.c:111
void kv_init(kv_store_t *kv, size_t capacity, size_t esize, uint32_t *keys, void *values, uint8_t *used)
Initializes a key-value store.
Definition kv_store.c:20
uint16_t foo
Definition main_demo5.c:58
abi_event ev
Definition rssi.c:45
Architecture independent timing functions.
pprz_bsem_t bsem
Definition thd_test.c:34
static void can_frame_cb(struct pprzcan_frame *rx_msg, UNUSED struct pprzaddr_can *src_addr, void *user_data)
Definition uavcan.c:81
void uavcan_init(void)
Initialize all uavcan interfaces.
Definition uavcan.c:225
void uavcan_transfer(struct uavcan_iface_t *iface, CanardTxTransfer *transfer)
Definition uavcan.c:268
static bool shouldAcceptTransfer(const CanardInstance *ins, uint64_t *out_data_type_signature, uint16_t data_type_id, CanardTransferType transfer_type, uint8_t source_node_id)
If we should accept this transfer.
Definition uavcan.c:155
static void uavcanInitIface(struct uavcan_iface_t *iface)
Initialize uavcan interface.
Definition uavcan.c:192
void uavcan_request(struct uavcan_iface_t *iface, uint8_t destination_node_id, CanardTxTransfer *transfer)
Definition uavcan.c:289
void uavcan_broadcast(struct uavcan_iface_t *iface, uint64_t data_type_signature, uint16_t data_type_id, uint8_t priority, const void *payload, uint16_t payload_len)
Legacy function Broadcast an uavcan message to a specific interface.
Definition uavcan.c:313
static void uavcan_tx(void *p)
Definition uavcan.c:100
static uavcan_event * uavcan_event_hd
Definition uavcan.c:43
void uavcan_response(struct uavcan_iface_t *iface, uint8_t destination_node_id, CanardTxTransfer *transfer)
Definition uavcan.c:332
void uavcan_bind(uint16_t data_type_id, uint64_t data_type_signature, uavcan_event *ev, uavcan_callback cb)
Bind to a receiving message from uavcan.
Definition uavcan.c:240
static void onTransferReceived(CanardInstance *ins, CanardRxTransfer *transfer)
Whenever a valid and 'accepted' transfer is received.
Definition uavcan.c:141
static uint8_t * get_transfer_id(struct uavcan_iface_t *iface, uint8_t destination_node_id, CanardTxTransfer *transfer)
Definition uavcan.c:252
pprz_mutex_t tx_mutex
Definition uavcan.h:49
uint8_t transfer_ids_values[UAVCAN_TID_STORE_CAPACITY]
Definition uavcan.h:64
void(* uavcan_callback)(struct uavcan_iface_t *iface, CanardRxTransfer *transfer)
Generic uavcan callback definition.
Definition uavcan.h:71
bool initialized
Definition uavcan.h:67
uint32_t transfer_ids_keys[UAVCAN_TID_STORE_CAPACITY]
Definition uavcan.h:63
struct pprzaddr_can can_net
Definition uavcan.h:45
pprz_bsem_t bsem
Definition uavcan.h:52
kv_store_t transfer_ids_store
Definition uavcan.h:66
#define UAVCAN_TID_STORE_CAPACITY
Definition uavcan.h:41
uint8_t transfer_ids_used[UAVCAN_TID_STORE_CAPACITY]
Definition uavcan.h:65
pprz_thread_t thread_tx
Definition uavcan.h:50
uint16_t nb_errors
Definition uavcan.h:60
uint8_t node_id
Definition uavcan.h:54
CanardInstance canard
Definition uavcan.h:55
uint8_t canard_memory_pool[1024 *2]
Definition uavcan.h:56
Main uavcan event structure for registering/calling callbacks.
Definition uavcan.h:74
uavcan interface structure
Definition uavcan.h:44
void uavcan_allocator_init(void)
void uavcan_init_reporting()
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned long long uint64_t
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
int transfer(const Mat *from, const image_t *to)