Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
cf3c636
Add stm32cube framework
bjsowa Jul 25, 2022
a1bb2d7
Add stm32cube serial transport
bjsowa Jul 26, 2022
a27c890
Allow nonblocking read
bjsowa Jul 26, 2022
f33a16e
Add some comments
bjsowa Jul 26, 2022
35fbb64
Don't wait until len bytes of data is available to read
bjsowa Jul 26, 2022
e77c93b
Merge remote-tracking branch 'origin/main' into stm32cube
bjsowa Aug 1, 2022
09be1ec
Move arduino CI package into subdirectory
bjsowa Aug 3, 2022
a114a71
Make the transport header compatible with C language
bjsowa Aug 3, 2022
3fdcc1c
Add example project for stm32cube framework
bjsowa Aug 3, 2022
ad2ba7c
Update CI workflow
bjsowa Aug 3, 2022
4fecbf7
Remove vscode artifacts
bjsowa Aug 3, 2022
2975d2f
Install and use CubeMX to generate code
bjsowa Aug 4, 2022
8828f03
Uncomment arduino ci job
bjsowa Aug 4, 2022
1d6a755
Allow setting buffer sizes that are not a power of 2
bjsowa Aug 4, 2022
44da965
Freeze ststm32 platform package version
bjsowa Aug 4, 2022
d7bbc0a
Update .github/workflows/ci.yml
bjsowa Aug 26, 2022
6dee3d2
Ignore vscode configuration
bjsowa Sep 2, 2022
9399a57
Don't include HAL libraries in clock_gettime
bjsowa Sep 2, 2022
b77f752
Create example project on nucleo-f103rb board
bjsowa Sep 2, 2022
0fa7672
Update CI to use new pio environment
bjsowa Sep 2, 2022
2e49658
Fix issues with clock_gettime implementation
bjsowa Sep 20, 2022
d5a0592
Add nucleo_767zi example to CI
bjsowa Sep 22, 2022
5552498
Set default colcon metas for nucleo boards
bjsowa Sep 22, 2022
a69ff65
Add nucleo board to supported boards
bjsowa Sep 22, 2022
19eabda
Merge remote-tracking branch 'microros/main' into stm32cube
bjsowa Oct 10, 2022
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
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@
"extraScript": "./extra_script.py"
},

"frameworks": "arduino",
"frameworks": "arduino, stm32cube",
"platforms": "teensy, https://github.com/platformio/platform-espressif32.git#feature/arduino-upstream, atmelsam, raspberrypi, ststm32"
}
34 changes: 34 additions & 0 deletions platform_code/stm32cube/clock_gettime.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <sys/time.h>

#if defined(STM32F0xx)
#include "stm32f0xx_hal.h"
#elif defined(STM32F1xx)
#include "stm32f1xx_hal.h"
#elif defined(STM32F2xx)
#include "stm32f2xx_hal.h"
#elif defined(STM32F3xx)
#include "stm32f3xx_hal.h"
#elif defined(STM32F4xx)
#include "stm32f4xx_hal.h"
#elif defined(STM32F7xx)
#include "stm32f7xx_hal.h"
#endif

constexpr uint64_t GETTICK_ROLLOVER_USECONDS = 4294967296000UL;

extern "C" int clock_gettime(clockid_t unused, struct timespec *tp) {
(void)unused;
static uint32_t rollover = 0;
static uint32_t last_measure = 0;

uint32_t m = HAL_GetTick();
rollover += (m < last_measure) ? 1 : 0;

uint64_t real_us =
(uint64_t)(m * 1000 + rollover * GETTICK_ROLLOVER_USECONDS);
tp->tv_sec = real_us / 1000000;
tp->tv_nsec = (real_us % 1000000) * 1000;
last_measure = m;

return 0;
}
Empty file.
107 changes: 107 additions & 0 deletions platform_code/stm32cube/serial/micro_ros_transport.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include <micro_ros_platformio.h>

static uint16_t rhead, rtail;
static volatile uint16_t thead, thead_next, ttail;
static uint32_t open_count = 0;

static void stream_flush(DMAStream *stream) {
static volatile bool mutex = false;

if ((stream->uart->gState == HAL_UART_STATE_READY) && !mutex) {
mutex = true;

if (thead != ttail) {
uint16_t len =
thead < ttail ? ttail - thead : stream->tbuffer_size - thead;
thead_next = (thead + len) & (stream->tbuffer_size - 1);
HAL_UART_Transmit_DMA(stream->uart, stream->tbuffer + thead, len);
}
mutex = false;
}
}

void uart_transfer_complete_callback(DMAStream *stream) {
thead = thead_next;
stream_flush(stream);
}

extern "C" {

bool platformio_transport_open(struct uxrCustomTransport *transport) {
DMAStream *stream = (DMAStream *)transport->args;

if (open_count == 0) {
rhead = rtail = thead = thead_next = ttail = 0;
HAL_UART_Receive_DMA(stream->uart, stream->rbuffer, stream->rbuffer_size);
}
open_count++;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use a integer for this?

Also, did you encounter any situation where open/close calls miss match?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my case, I used rmw_uros_ping_agent periodically to detect agent disconnects. The issue was that this function called open and close on the transport each time it was called, even when the transport was already opened. This is why I decided to ignore all nested open/close calls, hence I use integer to track the nesting level.

It's possible I used the library wrong. Let me know if that's the case or if you know a better way to deal with this problem.


return true;
}

bool platformio_transport_close(struct uxrCustomTransport *transport) {
DMAStream *stream = (DMAStream *)transport->args;

open_count--;
if (open_count == 0) {
HAL_UART_DMAStop(stream->uart);
}

return true;
}

size_t platformio_transport_write(struct uxrCustomTransport *transport,
const uint8_t *buf, size_t len,
uint8_t *errcode) {
DMAStream *stream = (DMAStream *)transport->args;

uint16_t n = len;
uint16_t buffer_available =
thead <= ttail ? stream->tbuffer_size - ttail + thead : thead - ttail;
if (n > buffer_available) n = buffer_available;

uint16_t n_tail =
n <= stream->tbuffer_size - ttail ? n : stream->tbuffer_size - ttail;

memcpy(stream->tbuffer + ttail, buf, n_tail);

if (n != n_tail) {
memcpy(stream->tbuffer, buf + n_tail, n - n_tail);
}

ttail = (ttail + n) & (stream->tbuffer_size - 1);

stream_flush(stream);

return n;
}

size_t platformio_transport_read(struct uxrCustomTransport *transport,
uint8_t *buf, size_t len, int timeout,
uint8_t *errcode) {
DMAStream *stream = (DMAStream *)transport->args;

int ms_used = 0;
while (true) {
__disable_irq();
rtail = stream->rbuffer_size - __HAL_DMA_GET_COUNTER(stream->uart->hdmarx);
__enable_irq();

uint16_t data_available =
rhead <= rtail ? rtail - rhead : stream->rbuffer_size - rhead + rtail;

if (data_available >= len || ms_used >= timeout) break;

HAL_Delay(1);
ms_used++;
}

size_t wrote = 0;
while ((rhead != rtail) && (wrote < len)) {
buf[wrote++] = stream->rbuffer[rhead];
rhead = (rhead + 1) & (stream->rbuffer_size - 1);
}

return wrote;
}
}
31 changes: 31 additions & 0 deletions platform_code/stm32cube/serial/micro_ros_transport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <rmw_microros/custom_transport.h>

#if defined(STM32F0xx)
#include "stm32f0xx_hal.h"
#elif defined(STM32F1xx)
#include "stm32f1xx_hal.h"
#elif defined(STM32F2xx)
#include "stm32f2xx_hal.h"
#elif defined(STM32F3xx)
#include "stm32f3xx_hal.h"
#elif defined(STM32F4xx)
#include "stm32f4xx_hal.h"
#elif defined(STM32F7xx)
#include "stm32f7xx_hal.h"
#endif

struct DMAStream {
UART_HandleTypeDef* uart;
uint16_t rbuffer_size;
uint8_t* rbuffer;
uint16_t tbuffer_size;
uint8_t* tbuffer;
};

static inline void set_microros_serial_transports(DMAStream& stream) {
rmw_uros_set_custom_transport(
true, &stream, platformio_transport_open, platformio_transport_close,
platformio_transport_write, platformio_transport_read);
}

void uart_transfer_complete_callback(DMAStream* stream);