Skip to content

Commit

Permalink
Merge pull request #139 from Firmament-Autopilot/staging/cuav
Browse files Browse the repository at this point in the history
[BSP] CUAV V5-Nano
  • Loading branch information
JcZou authored Dec 27, 2024
2 parents e83f9b4 + 6b97fa5 commit b3b1384
Show file tree
Hide file tree
Showing 94 changed files with 83,989 additions and 130 deletions.
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@
"svdFile": "target/cuav/v5_plus/STM32F7x5.svd",
"runToMain": true
},
{
"name": "CUAV V5 Nano Debug J-Link",
"type": "cortex-debug",
"request": "launch",
"cwd": "${workspaceRoot}",
"executable": "target/cuav/v5_nano/build/fmt_cuav-v5_nano.elf",
"serverpath": "${env:JLINK_SERVER}",
"servertype": "jlink",
"device": "STM32F765II",
"interface": "swd",
"armToolchainPath": "${env:RTT_EXEC_PATH}",
"serialNumber": "", //If you have more than one J-Link probe, add the serial number here.
"svdFile": "target/cuav/v5_nano/STM32F7x5.svd",
"runToMain": true
},
{
"name": "FMUv2 Debug J-Link",
"type": "cortex-debug",
Expand Down
8 changes: 5 additions & 3 deletions src/hal/serial/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ static rt_err_t hal_serial_control(struct rt_device* dev,

/**
* @brief serial isr handler
*
*
* @param serial serial device
* @param event serial isr event
*/
Expand All @@ -591,7 +591,9 @@ void hal_serial_isr(struct serial_device* serial, int event)

/* interrupt mode receive */
rx_fifo = (struct serial_rx_fifo*)serial->serial_rx;
RT_ASSERT(rx_fifo != RT_NULL);
if (rx_fifo == RT_NULL) {
return;
}

while (1) {
ch = serial->ops->getc(serial);
Expand Down Expand Up @@ -676,7 +678,7 @@ void hal_serial_isr(struct serial_device* serial, int event)

/**
* @brief register a serial device
*
*
* @param serial serial device
* @param name device name
* @param flag device flag
Expand Down
199 changes: 199 additions & 0 deletions src/module/mavproxy/mavlink_rtcm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
/******************************************************************************
* Copyright 2020 The Firmament Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/

#include <firmament.h>

#include "hal/serial/serial.h"
#include "module/mavproxy/mavproxy.h"
#include "module/mavproxy/mavproxy_config.h"

#define MAX_RTCM_DEV_NUM 5

/*
buffer for re-assembling RTCM data for GPS injection.
The 8 bit flags field in GPS_RTCM_DATA is interpreted as:
1 bit for "is fragmented"
2 bits for fragment number
5 bits for sequence number

The rtcm_buffer is allocated on first use. Once a block of data
is successfully reassembled it is injected into all active GPS
backends. This assumes we don't want more than 4*180=720 bytes
in a RTCM data block
*/
struct rtcm_buffer {
uint8_t fragments_received;
uint8_t sequence;
uint8_t fragment_count;
uint16_t total_length;
uint8_t buffer[MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN * 4];
}* rtcm_buffer;

static uint8_t rtcm_dev_num;
static rt_device_t rtcm_dev[MAX_RTCM_DEV_NUM];
static struct rt_completion tx_cplt[MAX_RTCM_DEV_NUM];

static rt_err_t rtcm_tx_done(rt_device_t dev, void* buffer)
{
for (uint8_t i = 0; i < rtcm_dev_num; i++) {
if (dev == rtcm_dev[i]) {
rt_completion_done(&tx_cplt[i]);
}
}

return RT_EOK;
}

static void inject_data(const uint8_t* data, uint16_t len)
{
// TODO: check write complete before next write;
for (uint8_t i = 0; i < rtcm_dev_num; i++) {
if (rtcm_dev[i] != NULL) {
if (rt_device_write(rtcm_dev[i], 0, data, len) > 0) {
/* wait write complete (synchronized write) */
rt_completion_wait(&tx_cplt[i], TICKS_FROM_MS(100));
}
}
}
}

void handle_gps_rtcm_data(const mavlink_message_t* msg)
{
mavlink_gps_rtcm_data_t packet;
mavlink_msg_gps_rtcm_data_decode(msg, &packet);

// printf("rtcm pkg, len:%d fragmented:%d, fragment_id:%d, seq_id:%d\n", packet.len, packet.flags & 1, (packet.flags >> 1U) & 0x03, (packet.flags >> 3U) & 0x1F);

if (packet.len > sizeof(packet.data)) {
// invalid packet
return;
}

if ((packet.flags & 1) == 0) {
// it is not fragmented, pass direct
inject_data(packet.data, packet.len);
return;
}

// see if we need to allocate re-assembly buffer
if (rtcm_buffer == NULL) {
rtcm_buffer = (struct rtcm_buffer*)rt_malloc(sizeof(*rtcm_buffer));
if (rtcm_buffer == NULL) {
// nothing to do but discard the data
return;
}
}

const uint8_t fragment = (packet.flags >> 1U) & 0x03;
const uint8_t sequence = (packet.flags >> 3U) & 0x1F;
uint8_t* start_of_fragment_in_buffer = &rtcm_buffer->buffer[MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN * (uint16_t)fragment];
bool should_clear_previous_fragments = false;

if (rtcm_buffer->fragments_received) {
const bool sequence_nr_changed = rtcm_buffer->sequence != sequence;
const bool seen_this_fragment_index = rtcm_buffer->fragments_received & (1U << fragment);

// check whether this is a duplicate fragment. If it is, we can
// return early.
if (!sequence_nr_changed && seen_this_fragment_index && !rt_memcmp(start_of_fragment_in_buffer, packet.data, packet.len)) {
return;
}

// not a duplicate
should_clear_previous_fragments = sequence_nr_changed || seen_this_fragment_index;
}

if (should_clear_previous_fragments) {
// we have one or more partial fragments already received
// which conflict with the new fragment, discard previous fragments
rtcm_buffer->fragment_count = 0;
// rtcm_stats.fragments_discarded += __builtin_popcount(rtcm_buffer->fragments_received);
rtcm_buffer->fragments_received = 0;
}

// add this fragment
rtcm_buffer->sequence = sequence;
rtcm_buffer->fragments_received |= (1U << fragment);

// copy the data
rt_memcpy(start_of_fragment_in_buffer, packet.data, packet.len);

// when we get a fragment of less than max size then we know the
// number of fragments. Note that this means if you want to send a
// block of RTCM data of an exact multiple of the buffer size you
// need to send a final packet of zero length
if (packet.len < MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN) {
rtcm_buffer->fragment_count = fragment + 1;
rtcm_buffer->total_length = (MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN * fragment) + packet.len;
} else if (rtcm_buffer->fragments_received == 0x0F) {
// special case of 4 full fragments
rtcm_buffer->fragment_count = 4;
rtcm_buffer->total_length = MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN * 4;
}

// see if we have all fragments
if (rtcm_buffer->fragment_count != 0 && rtcm_buffer->fragments_received == (1U << rtcm_buffer->fragment_count) - 1) {
// we have them all, inject
inject_data(rtcm_buffer->buffer, rtcm_buffer->total_length);
rtcm_buffer->fragment_count = 0;
rtcm_buffer->fragments_received = 0;
}
}

fmt_err_t mavlink_rtcm_device_init(void)
{
mavproxy_device_info* rtcm_dev_list = mavproxy_get_rtcm_dev_list();
uint8_t dev_num = mavproxy_get_rtcm_dev_num();

for (uint8_t i = 0; i < dev_num && i < MAX_RTCM_DEV_NUM; i++) {
if (strcmp(rtcm_dev_list[i].type, "serial") == 0) {
rt_device_t dev = rt_device_find(rtcm_dev_list[i].name);

if (dev == NULL) {
continue;
}

/* If device is not opened, then open it */
if (!(dev->open_flag & RT_DEVICE_OFLAG_OPEN)) {
rt_uint16_t oflag = RT_DEVICE_OFLAG_WRONLY;

if (dev->flag & RT_DEVICE_FLAG_DMA_TX) {
oflag |= RT_DEVICE_FLAG_DMA_TX;
}

RT_TRY(rt_device_open(dev, oflag));

serial_dev_t serial_dev = (serial_dev_t)dev;
mavproxy_serial_dev_config* config = rtcm_dev_list[i].config;

if (serial_dev->config.baud_rate != config->baudrate) {
struct serial_configure pconfig = serial_dev->config;
pconfig.baud_rate = config->baudrate;

RT_TRY(rt_device_control(dev, RT_DEVICE_CTRL_CONFIG, &pconfig));
}
}

rt_completion_init(&tx_cplt[i]);
/* set callback functions */
rt_device_set_tx_complete(dev, rtcm_tx_done);

rtcm_dev[rtcm_dev_num++] = dev;
}
}

return FMT_EOK;
}
34 changes: 34 additions & 0 deletions src/module/mavproxy/mavlink_rtcm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/******************************************************************************
* Copyright 2020 The Firmament Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/

#ifndef MAVLINK_RTCM_H__
#define MAVLINK_RTCM_H__

#include <firmament.h>
#include <mavlink.h>

#ifdef __cplusplus
extern "C" {
#endif

void handle_gps_rtcm_data(const mavlink_message_t* msg);
fmt_err_t mavlink_rtcm_device_init(void);

#ifdef __cplusplus
}
#endif

#endif
29 changes: 17 additions & 12 deletions src/module/mavproxy/mavproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,12 @@ static void dump_period_msg(uint8_t chan)

/**
* Register to send a mavlink message periodically
*
*
* @param msgid mavlink message id
* @param msg_rate_hz message send rate in Hz
* @param msg_pack_cb callback function to prepare the mavlink message data
* @param auto_start auto start of sending the message
*
*
* @return FMT Errors
*/
fmt_err_t mavproxy_register_period_msg(uint8_t chan, uint8_t msgid, uint16_t msg_rate_hz,
Expand Down Expand Up @@ -165,11 +165,11 @@ fmt_err_t mavproxy_register_period_msg(uint8_t chan, uint8_t msgid, uint16_t msg

/**
* Send a mavlink message via the mavproxy device
*
*
* @param msg mavlink message
* @param sync true: wait until the mavproxy device is available and send message
* false: push the message into a queue and return directly
*
*
* @return FMT Errors
*/
fmt_err_t mavproxy_send_immediate_msg(uint8_t chan, const mavlink_message_t* msg, bool sync)
Expand Down Expand Up @@ -214,11 +214,11 @@ fmt_err_t mavproxy_send_immediate_msg(uint8_t chan, const mavlink_message_t* msg

/**
* Send a event to mavproxy
*
*
* @brief the event will be handled in mavproxy main loop
*
*
* @param event_set event set
*
*
* @return FMT Errors
*/
fmt_err_t mavproxy_send_event(uint8_t chan, uint32_t event_set)
Expand All @@ -232,7 +232,7 @@ fmt_err_t mavproxy_send_event(uint8_t chan, uint32_t event_set)

/**
* Get mavlink system information. sysid and compid
*
*
* @return mavlink system
*/
mavlink_system_t mavproxy_get_system(void)
Expand All @@ -242,10 +242,10 @@ mavlink_system_t mavproxy_get_system(void)

/**
* Set mavproxy channel.
*
*
* @param chan channel of mavproxy device
* @param devid mavproxy device id
*
*
* @return FMT Errors
*/
fmt_err_t mavproxy_set_device(uint8_t chan, uint8_t devid)
Expand All @@ -267,7 +267,7 @@ fmt_err_t mavproxy_set_device(uint8_t chan, uint8_t devid)

/**
* @brief Main loop for mavproxy channel
*
*
* @param chan mavproxy channel
*/
void mavproxy_channel_loop(uint8_t chan)
Expand All @@ -280,6 +280,11 @@ void mavproxy_channel_loop(uint8_t chan)
return;
}

if (chan == MAVPROXY_GCS_CHAN) {
/* init mavlink rtcm devices */
mavlink_rtcm_device_init();
}

/* Set mavproxy new channel to 0 if not set. Here we need critical section
since the new channel can possible be set in usb ISR. */
OS_ENTER_CRITICAL;
Expand Down Expand Up @@ -329,7 +334,7 @@ void mavproxy_channel_loop(uint8_t chan)

/**
* Initialize the mavproxy module.
*
*
* @return FMT Errors
*/
fmt_err_t mavproxy_init(void)
Expand Down
Loading

0 comments on commit b3b1384

Please sign in to comment.