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
31#ifndef UAVCAN_NODE_ID
32#define UAVCAN_NODE_ID 100
33#endif
34
35#ifndef UAVCAN_BAUDRATE
36#define UAVCAN_BAUDRATE 1000000
37#endif
38
40
41#if UAVCAN_USE_CAN1
42#ifndef UAVCAN_CAN1_NODE_ID
43#define UAVCAN_CAN1_NODE_ID UAVCAN_NODE_ID
44#endif
45
46#ifndef UAVCAN_CAN1_BAUDRATE
47#define UAVCAN_CAN1_BAUDRATE UAVCAN_BAUDRATE
48#endif
49
51 uint64_t data_type_signature;
52 uint16_t data_type_id;
54 uint16_t payload_len;
55 uint8_t *payload;
56};
57
58
59struct uavcan_iface_t uavcan1 = {
60 .can_net = {.can_ifindex = 1},
61 .can_baudrate = UAVCAN_CAN1_BAUDRATE,
62 .node_id = UAVCAN_CAN1_NODE_ID,
63 .transfer_id = 0,
64 .initialized = false
65};
66#endif
67
68#if UAVCAN_USE_CAN2
69#ifndef UAVCAN_CAN2_NODE_ID
70#define UAVCAN_CAN2_NODE_ID UAVCAN_NODE_ID
71#endif
72
73#ifndef UAVCAN_CAN2_BAUDRATE
74#define UAVCAN_CAN2_BAUDRATE UAVCAN_BAUDRATE
75#endif
76
77
78struct uavcan_iface_t uavcan2 = {
79 .can_net = {.can_ifindex = 2},
80 .can_baudrate = UAVCAN_CAN2_BAUDRATE,
81 .node_id = UAVCAN_CAN2_NODE_ID,
82 .transfer_id = 0,
83 .initialized = false
84};
85#endif
86
87
88static void can_frame_cb(struct pprzcan_frame* rx_msg, UNUSED struct pprzaddr_can* src_addr, void* user_data) {
89 struct uavcan_iface_t *iface = (struct uavcan_iface_t *)user_data;
90
91 pprz_mtx_lock(&iface->mutex);
92
93 CanardCANFrame rx_frame = {0};
94 memcpy(rx_frame.data, rx_msg->data, 8);
95 rx_frame.data_len = rx_msg->len;
96 if (rx_msg->can_id & CAN_FRAME_EFF) {
97 rx_frame.id = CANARD_CAN_FRAME_EFF | (rx_msg->can_id & CAN_EID_MASK);
98 } else {
99 rx_frame.id = rx_msg->can_id & CAN_SID_MASK;
100 }
101
102 // Let canard handle the frame
103 canardHandleRxFrame(&iface->canard, &rx_frame, rx_msg->timestamp);
104
105 pprz_mtx_unlock(&iface->mutex);
106}
107
108
110
111/*
112 * Transmitter thread.
113 */
114static void uavcan_tx(void* p)
115{
116 struct uavcan_iface_t *iface = (struct uavcan_iface_t *)p;
117 uint8_t err_cnt = 0;
118
119 while (true) {
120 pprz_bsem_wait(&iface->bsem);
121
122 pprz_mtx_lock(&iface->mutex);
123
124
125 // read the Tx FIFO to canard
126 pprz_mtx_lock(&iface->tx_fifo_mutex);
127 while(true) {
128 struct uavcan_msg_header_t header;
129 int ret = circular_buffer_get(&iface->_tx_fifo, (uint8_t*)&header, sizeof(header));
130 if(ret < 0) {break;}
131 if(header.payload_len >= UAVCAN_MSG_MAX_SIZE) {
132 chSysHalt("UAVCAN_MSG_MAX_SIZE too small");
133 }
135 if(ret < 0) {break;}
136 canardBroadcast(&iface->canard,
137 header.data_type_signature,
138 header.data_type_id, &iface->transfer_id,
139 header.priority, msg_payload, header.payload_len);
140 }
141 pprz_mtx_unlock(&iface->tx_fifo_mutex);
142
143 for (const CanardCANFrame *txf = NULL; (txf = canardPeekTxQueue(&iface->canard)) != NULL;) {
144 struct pprzcan_frame tx_msg;
145 memcpy(tx_msg.data, txf->data, 8);
146 tx_msg.len = txf->data_len;
148
149 if (!can_transmit_frame(&tx_msg, &iface->can_net)) {
150 err_cnt = 0;
151 canardPopTxQueue(&iface->canard);
152 } else {
153 // After 5 retries giveup and clean full queue
154 if (err_cnt >= 5) {
155 err_cnt = 0;
156 while (canardPeekTxQueue(&iface->canard)) { canardPopTxQueue(&iface->canard); }
157 continue;
158 }
159
160 // Timeout - just exit and try again later
161 pprz_mtx_unlock(&iface->mutex);
163 pprz_mtx_lock(&iface->mutex);
164 continue;
165 }
166 }
167 pprz_mtx_unlock(&iface->mutex);
168 }
169}
170
175{
176 struct uavcan_iface_t *iface = (struct uavcan_iface_t *)ins->user_reference;
177
178 // Go through all registered callbacks and call function callback if found
179 for (uavcan_event *ev = uavcan_event_hd; ev; ev = ev->next) {
180 if (transfer->data_type_id == ev->data_type_id) {
181 ev->cb(iface, transfer);
182 }
183 }
184}
185
191 uint16_t data_type_id,
194{
195
196 // Go through all registered callbacks and return signature if found
197 for (uavcan_event *ev = uavcan_event_hd; ev; ev = ev->next) {
198 if (data_type_id == ev->data_type_id) {
199 *out_data_type_signature = ev->data_type_signature;
200 return true;
201 }
202 }
203 // No callback found return
204 return false;
205}
206
207
212{
213 pprz_mtx_init(&iface->mutex);
214 pprz_bsem_init(&iface->bsem, true);
215 pprz_mtx_init(&iface->tx_fifo_mutex);
216
217 // Initialize tx fifo
218 circular_buffer_init(&iface->_tx_fifo, iface->_tx_fifo_buffer, UAVCAN_TX_FIFO_SIZE);
219
220 // Initialize canard
221 canardInit(&iface->canard, iface->canard_memory_pool, sizeof(iface->canard_memory_pool),
223 // Update the uavcan node ID
224 canardSetLocalNodeID(&iface->canard, iface->node_id);
225
226 // Start the receiver and transmitter thread
227 can_register_callback(can_frame_cb, &iface->can_net, (void *)iface);
228
229 if(!pprz_thread_create(&iface->thread_tx, 2048, "uavcan_tx", NORMALPRIO+7, uavcan_tx, (void *)iface)) {
230 iface->initialized = true;
231 }
232}
233
237void uavcan_init(void)
238{
239#if UAVCAN_USE_CAN1
241#endif
242#if UAVCAN_USE_CAN2
244#endif
245}
246
250void uavcan_bind(uint16_t data_type_id, uint64_t data_type_signature, uavcan_event *ev, uavcan_callback cb)
251{
252 // Configure the event
253 ev->data_type_id = data_type_id;
254 ev->data_type_signature = data_type_signature;
255 ev->cb = cb;
257
258 // Switch the head
260}
261
265void uavcan_broadcast(struct uavcan_iface_t *iface, uint64_t data_type_signature, uint16_t data_type_id,
266 uint8_t priority, const void *payload,
267 uint16_t payload_len)
268{
269 if (!iface->initialized) { return; }
270 pprz_mtx_lock(&iface->tx_fifo_mutex);
271
272 struct uavcan_msg_header_t header = {
273 .data_type_signature = data_type_signature,
274 .data_type_id = data_type_id,
275 .priority = priority,
276 .payload_len = payload_len
277 };
278
279 if(circular_buffer_put(&iface->_tx_fifo, (uint8_t*)&header, sizeof(header)) < 0) {
280 // fail to post header
281 pprz_mtx_unlock(&iface->tx_fifo_mutex);
282 return;
283 }
284
285 if(circular_buffer_put(&iface->_tx_fifo, payload, payload_len) < 0) {
286 // fail to post payload. Remove the header from the fifo
287 circular_buffer_drop(&iface->_tx_fifo);
288 pprz_mtx_unlock(&iface->tx_fifo_mutex);
289 return;
290 }
291 pprz_mtx_unlock(&iface->tx_fifo_mutex);
292
293 // Wake Tx thread
294 pprz_bsem_signal(&iface->bsem);
295}
struct abi_struct * next
Definition abi_common.h:70
abi_callback cb
Definition abi_common.h:69
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
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)
void(* uavcan_callback)(struct uavcan_iface_t *iface, CanardRxTransfer *transfer)
Generic uavcan callback definition.
Definition uavcan.h:73
#define UAVCAN_TX_FIFO_SIZE
Definition uavcan.h:37
#define UAVCAN_MSG_MAX_SIZE
Definition uavcan.h:41
Main uavcan event structure for registering/calling callbacks.
Definition uavcan.h:76
int circular_buffer_put(struct circular_buffer *cb, const uint8_t *buf, size_t len)
Copy buf in the circular buffer.
void circular_buffer_init(struct circular_buffer *cb, uint8_t *buffer, size_t len)
initialize a circular buffer.
int circular_buffer_get(struct circular_buffer *cb, uint8_t *buf, size_t len)
copy the next buffer available in cb to buf.
int circular_buffer_drop(struct circular_buffer *cb)
Drop last inserted record.
static float p[2][2]
uint16_t foo
Definition main_demo5.c:58
abi_event ev
Definition rssi.c:45
struct pprzaddr_can can_net
Definition uavcan.h:47
uavcan interface structure
Definition uavcan.h:46
uint8_t msg_payload[UAVCAN_MSG_MAX_SIZE]
Definition uavcan.c:109
static void can_frame_cb(struct pprzcan_frame *rx_msg, UNUSED struct pprzaddr_can *src_addr, void *user_data)
Definition uavcan.c:88
void uavcan_init(void)
Initialize all uavcan interfaces.
Definition uavcan.c:237
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:189
static void uavcanInitIface(struct uavcan_iface_t *iface)
Initialize uavcan interface.
Definition uavcan.c:211
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)
Broadcast an uavcan message to a specific interface.
Definition uavcan.c:265
static void uavcan_tx(void *p)
Definition uavcan.c:114
static uavcan_event * uavcan_event_hd
Definition uavcan.c:39
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:250
static void onTransferReceived(CanardInstance *ins, CanardRxTransfer *transfer)
Whenever a valid and 'accepted' transfer is received.
Definition uavcan.c:174
unsigned short uint16_t
Typedef defining 16 bit unsigned short 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)