diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 31a7248d..f85da831 100755
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,30 +1,105 @@
name: CI
on:
- pull_request:
- branches:
- - '**'
+ workflow_dispatch:
+ pull_request:
+ branches:
+ - "**"
jobs:
+ micro_ros_platformio_arduino:
+ runs-on: ubuntu-20.04
+ container: ubuntu:20.04
- micro_ros_platformio:
- runs-on: ubuntu-20.04
- container: ubuntu:20.04
+ strategy:
+ fail-fast: false
+ matrix:
+ pio-environment:
+ - teensy41
+ - teensy40
+ - teensy36
+ - teensy35
+ - teensy31
+ - due
+ - zero
+ - olimex_e407
+ - esp32dev
+ - nanorp2040connect
+ - portenta_h7_m7
+ - teensy41_eth
+ - nanorp2040connect_wifi
+ - portenta_h7_m7_wifi
+ - esp32dev_wifi
+ - portenta_h7_m7_galactic
+ - portenta_h7_m7_foxy
+ - portenta_h7_m7_rolling
+ - teensy41_custom
+ - pico
- strategy:
- fail-fast: false
- matrix:
- platform: [teensy41, teensy40, teensy36, teensy35, teensy31, due, zero, olimex_e407, esp32dev, nanorp2040connect, portenta_h7_m7, teensy41_eth, nanorp2040connect_wifi, portenta_h7_m7_wifi, esp32dev_wifi, portenta_h7_m7_galactic, portenta_h7_m7_foxy, portenta_h7_m7_rolling, teensy41_custom, pico]
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ path: repo
+ - name: Install environment
+ uses: ./repo/.github/actions/platformio-env
+ - name: Build
+ shell: bash
+ run: |
+ export PATH=$PATH:~/.platformio/penv/bin
+ cd repo/ci/arduino
+ pio run -e ${{ matrix.pio-environment }}
- steps:
- - uses: actions/checkout@v3
- with:
- path: repo
- - name: Install environment
- uses: ./repo/.github/actions/platformio-env
- - name: Build
- shell: bash
- run: |
- export PATH=$PATH:~/.platformio/penv/bin
- cd repo/ci
- pio run -e ${{ matrix.platform }}
+ micro_ros_platformio_stm32cube:
+ runs-on: ubuntu-20.04
+ container: ubuntu:20.04
+
+ strategy:
+ fail-fast: false
+ matrix:
+ pio-environment:
+ - nucleo_f103rb
+ - nucleo_f767zi
+
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ path: repo
+ - name: Install STM32CubeMX
+ env:
+ CUBEMX_LINK: http://files.fictionlab.pl/en.stm32cubemx-lin_v6-3-0.zip
+ run: |
+ apt update
+ export DEBIAN_FRONTEND=noninteractive
+ apt install -y wget unzip python3-pip expect fontconfig xvfb libxrender1 libxtst6 libxi6
+ wget -q -O cubemx.zip $CUBEMX_LINK
+ unzip -q cubemx.zip -d cubemx
+ expect -f - < `wifi` | `colcon.meta` |
| `nanorp2040connect` | `raspberrypi` | `arduino` | `serial`
`wifi_nina` | `colcon_verylowmem.meta` |
| `pico` | `raspberrypi` | `arduino` | `serial` | `colcon.meta`|
+| `nucleo_f103rb` | `ststm32` | `stm32cube` | `serial` | `colcon_verylowmem.meta` |
+| `nucleo_f767zi` | `ststm32` | `stm32cube` | `serial` | `colcon.meta`|
The community is encouraged to open pull request with custom use cases.
diff --git a/ci/.gitignore b/ci/arduino/.gitignore
similarity index 100%
rename from ci/.gitignore
rename to ci/arduino/.gitignore
diff --git a/ci/custom.meta b/ci/arduino/custom.meta
similarity index 100%
rename from ci/custom.meta
rename to ci/arduino/custom.meta
diff --git a/ci/extra_packages/extra_packages.repos b/ci/arduino/extra_packages/extra_packages.repos
similarity index 100%
rename from ci/extra_packages/extra_packages.repos
rename to ci/arduino/extra_packages/extra_packages.repos
diff --git a/ci/extra_packages/my_custom_message/CMakeLists.txt b/ci/arduino/extra_packages/my_custom_message/CMakeLists.txt
similarity index 100%
rename from ci/extra_packages/my_custom_message/CMakeLists.txt
rename to ci/arduino/extra_packages/my_custom_message/CMakeLists.txt
diff --git a/ci/extra_packages/my_custom_message/msg/MyCustomMessage.msg b/ci/arduino/extra_packages/my_custom_message/msg/MyCustomMessage.msg
similarity index 100%
rename from ci/extra_packages/my_custom_message/msg/MyCustomMessage.msg
rename to ci/arduino/extra_packages/my_custom_message/msg/MyCustomMessage.msg
diff --git a/ci/extra_packages/my_custom_message/package.xml b/ci/arduino/extra_packages/my_custom_message/package.xml
similarity index 100%
rename from ci/extra_packages/my_custom_message/package.xml
rename to ci/arduino/extra_packages/my_custom_message/package.xml
diff --git a/ci/platformio.ini b/ci/arduino/platformio.ini
similarity index 92%
rename from ci/platformio.ini
rename to ci/arduino/platformio.ini
index c7becb18..59b02b1f 100644
--- a/ci/platformio.ini
+++ b/ci/arduino/platformio.ini
@@ -6,7 +6,7 @@ framework = arduino
board_microros_transport = serial
board_microros_distro = galactic
lib_deps =
- ../
+ ../../
; Foxy test
[env:portenta_h7_m7_foxy]
@@ -16,7 +16,7 @@ framework = arduino
board_microros_transport = serial
board_microros_distro = foxy
lib_deps =
- ../
+ ../../
; Rolling test
[env:portenta_h7_m7_rolling]
@@ -26,7 +26,7 @@ framework = arduino
board_microros_transport = serial
board_microros_distro = rolling
lib_deps =
- ../
+ ../../
; Serial platforms
@@ -36,7 +36,7 @@ board = portenta_h7_m7
framework = arduino
board_microros_transport = serial
lib_deps =
- ../
+ ../../
[env:teensy41]
platform = teensy
@@ -44,7 +44,7 @@ board = teensy41
framework = arduino
board_microros_transport = serial
lib_deps =
- ../
+ ../../
[env:teensy40]
platform = teensy
@@ -52,7 +52,7 @@ board = teensy40
framework = arduino
board_microros_transport = serial
lib_deps =
- ../
+ ../../
[env:teensy36]
platform = teensy
@@ -60,7 +60,7 @@ board = teensy36
framework = arduino
board_microros_transport = serial
lib_deps =
- ../
+ ../../
[env:teensy35]
platform = teensy
@@ -68,7 +68,7 @@ board = teensy35
framework = arduino
board_microros_transport = serial
lib_deps =
- ../
+ ../../
[env:teensy31]
platform = teensy
@@ -76,7 +76,7 @@ board = teensy31
framework = arduino
board_microros_transport = serial
lib_deps =
- ../
+ ../../
[env:due]
platform = atmelsam
@@ -84,7 +84,7 @@ board = due
framework = arduino
board_microros_transport = serial
lib_deps =
- ../
+ ../../
[env:zero]
platform = atmelsam
@@ -92,7 +92,7 @@ board = zero
framework = arduino
board_microros_transport = serial
lib_deps =
- ../
+ ../../
[env:olimex_e407]
platform = ststm32
@@ -100,7 +100,7 @@ board = olimex_e407
framework = arduino
board_microros_transport = serial
lib_deps =
- ../
+ ../../
[env:esp32dev]
platform = espressif32
@@ -108,7 +108,7 @@ board = esp32dev
framework = arduino
board_microros_transport = serial
lib_deps =
- ../
+ ../../
[env:nanorp2040connect]
platform = raspberrypi
@@ -117,7 +117,7 @@ framework = arduino
lib_ldf_mode = chain+
board_microros_transport = serial
lib_deps =
- ../
+ ../../
[env:pico]
platform = raspberrypi
@@ -126,7 +126,7 @@ framework = arduino
lib_ldf_mode = chain+
board_microros_transport = serial
lib_deps =
- ../
+ ../../
; Ethernet platforms
@@ -136,7 +136,7 @@ board = teensy41
framework = arduino
board_microros_transport = native_ethernet
lib_deps =
- ../
+ ../../
; WiFi platforms
@@ -146,7 +146,7 @@ board = portenta_h7_m7
framework = arduino
board_microros_transport = wifi
lib_deps =
- ../
+ ../../
[env:esp32dev_wifi]
platform = espressif32
@@ -154,7 +154,7 @@ board = esp32dev
framework = arduino
board_microros_transport = wifi
lib_deps =
- ../
+ ../../
[env:nanorp2040connect_wifi]
platform = raspberrypi
@@ -163,7 +163,7 @@ framework = arduino
board_microros_transport = wifi_nina
lib_deps =
arduino-libraries/WiFiNINA@^1.8.13
- ../
+ ../../
; Custom transports
@@ -173,4 +173,4 @@ board = teensy41
framework = arduino
board_microros_transport = custom
lib_deps =
- ../
+ ../../
diff --git a/ci/src/main.cpp b/ci/arduino/src/main.cpp
similarity index 100%
rename from ci/src/main.cpp
rename to ci/arduino/src/main.cpp
diff --git a/ci/stm32cube/.gitignore b/ci/stm32cube/.gitignore
new file mode 100644
index 00000000..3b8da3a4
--- /dev/null
+++ b/ci/stm32cube/.gitignore
@@ -0,0 +1,2 @@
+.pio
+.vscode
\ No newline at end of file
diff --git a/ci/stm32cube/Src/main.c b/ci/stm32cube/Src/main.c
new file mode 100644
index 00000000..43db0e75
--- /dev/null
+++ b/ci/stm32cube/Src/main.c
@@ -0,0 +1,103 @@
+/* USER CODE BEGIN Includes */
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+/* USER CODE END Includes */
+
+/* USER CODE BEGIN PD */
+#define RCCHECK(fn) \
+ { \
+ rcl_ret_t temp_rc = fn; \
+ if ((temp_rc != RCL_RET_OK)) { \
+ Error_Handler(); \
+ } \
+ }
+#define RCSOFTCHECK(fn) \
+ { \
+ rcl_ret_t temp_rc = fn; \
+ if ((temp_rc != RCL_RET_OK)) { \
+ } \
+ }
+/* USER CODE END PD */
+
+/* USER CODE BEGIN PV */
+static rcl_publisher_t publisher;
+static std_msgs__msg__Int32 msg;
+static rclc_executor_t executor;
+static rclc_support_t support;
+static rcl_allocator_t allocator;
+static rcl_node_t node;
+static rcl_timer_t timer;
+
+static uint8_t uart_rbuffer[512];
+static uint8_t uart_tbuffer[512];
+static struct DMAStream stream = {
+ .uart = &UART_HANDLE,
+ .rbuffer_size = 512,
+ .rbuffer = uart_rbuffer,
+ .tbuffer_size = 512,
+ .tbuffer = uart_tbuffer,
+};
+/* USER CODE END PV */
+
+/* USER CODE BEGIN 0 */
+void timer_callback(rcl_timer_t *timer, int64_t last_call_time) {
+ RCLC_UNUSED(last_call_time);
+ if (timer != NULL) {
+ RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL));
+ msg.data++;
+ }
+}
+
+void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
+ if (huart == &UART_HANDLE) {
+ uart_transfer_complete_callback(&stream);
+ }
+}
+/* USER CODE END 0 */
+
+int main(void) {
+ /* USER CODE BEGIN 2 */
+ set_microros_serial_transports(&stream);
+
+ allocator = rcl_get_default_allocator();
+
+ // create init_options
+ RCCHECK(rclc_support_init(&support, 0, NULL, &allocator));
+
+ // create node
+ RCCHECK(
+ rclc_node_init_default(&node, "microros_platformio_node", "", &support));
+
+ // create publisher
+ RCCHECK(rclc_publisher_init_default(
+ &publisher, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32),
+ "microros_platformio_publisher"));
+
+ // create timer,
+ RCCHECK(rclc_timer_init_default(&timer, &support, RCL_MS_TO_NS(100),
+ timer_callback));
+
+ // create executor
+ RCCHECK(rclc_executor_init(&executor, &support.context, 1, &allocator));
+ RCCHECK(rclc_executor_add_timer(&executor, &timer));
+
+ msg.data = 0;
+ /* USER CODE END 2 */
+
+ /* Infinite loop */
+ /* USER CODE BEGIN WHILE */
+ while (1) {
+ RCSOFTCHECK(rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100)));
+ /* USER CODE END WHILE */
+
+ /* USER CODE BEGIN 3 */
+ }
+ /* USER CODE END 3 */
+}
diff --git a/ci/stm32cube/ioc/nucleo_f103rb.ioc b/ci/stm32cube/ioc/nucleo_f103rb.ioc
new file mode 100644
index 00000000..ff9ae9ff
--- /dev/null
+++ b/ci/stm32cube/ioc/nucleo_f103rb.ioc
@@ -0,0 +1,176 @@
+#MicroXplorer Configuration settings - do not modify
+Dma.Request0=USART2_RX
+Dma.Request1=USART2_TX
+Dma.RequestsNb=2
+Dma.USART2_RX.0.Direction=DMA_PERIPH_TO_MEMORY
+Dma.USART2_RX.0.Instance=DMA1_Channel6
+Dma.USART2_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE
+Dma.USART2_RX.0.MemInc=DMA_MINC_ENABLE
+Dma.USART2_RX.0.Mode=DMA_CIRCULAR
+Dma.USART2_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
+Dma.USART2_RX.0.PeriphInc=DMA_PINC_DISABLE
+Dma.USART2_RX.0.Priority=DMA_PRIORITY_VERY_HIGH
+Dma.USART2_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
+Dma.USART2_TX.1.Direction=DMA_MEMORY_TO_PERIPH
+Dma.USART2_TX.1.Instance=DMA1_Channel7
+Dma.USART2_TX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE
+Dma.USART2_TX.1.MemInc=DMA_MINC_ENABLE
+Dma.USART2_TX.1.Mode=DMA_NORMAL
+Dma.USART2_TX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
+Dma.USART2_TX.1.PeriphInc=DMA_PINC_DISABLE
+Dma.USART2_TX.1.Priority=DMA_PRIORITY_VERY_HIGH
+Dma.USART2_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
+File.Version=6
+GPIO.groupedBy=Group By Peripherals
+KeepUserPlacement=false
+Mcu.Family=STM32F1
+Mcu.IP0=DMA
+Mcu.IP1=NVIC
+Mcu.IP2=RCC
+Mcu.IP3=SYS
+Mcu.IP4=USART2
+Mcu.IPNb=5
+Mcu.Name=STM32F103R(8-B)Tx
+Mcu.Package=LQFP64
+Mcu.Pin0=PC13-TAMPER-RTC
+Mcu.Pin1=PC14-OSC32_IN
+Mcu.Pin10=PB3
+Mcu.Pin11=VP_SYS_VS_Systick
+Mcu.Pin2=PC15-OSC32_OUT
+Mcu.Pin3=PD0-OSC_IN
+Mcu.Pin4=PD1-OSC_OUT
+Mcu.Pin5=PA2
+Mcu.Pin6=PA3
+Mcu.Pin7=PA5
+Mcu.Pin8=PA13
+Mcu.Pin9=PA14
+Mcu.PinsNb=12
+Mcu.ThirdPartyNb=0
+Mcu.UserConstants=
+Mcu.UserName=STM32F103RBTx
+MxCube.Version=6.3.0
+MxDb.Version=DB.6.0.30
+NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.DMA1_Channel6_IRQn=true\:0\:0\:false\:false\:true\:false\:true
+NVIC.DMA1_Channel7_IRQn=true\:0\:0\:false\:false\:true\:false\:true
+NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.EXTI15_10_IRQn=true\:0\:0\:false\:false\:true\:true\:true
+NVIC.ForceEnableDMAVector=true
+NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
+NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:true\:true
+NVIC.USART2_IRQn=true\:0\:0\:false\:false\:true\:true\:true
+NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+PA13.GPIOParameters=GPIO_Label
+PA13.GPIO_Label=TMS
+PA13.Locked=true
+PA13.Mode=Serial_Wire
+PA13.Signal=SYS_JTMS-SWDIO
+PA14.GPIOParameters=GPIO_Label
+PA14.GPIO_Label=TCK
+PA14.Locked=true
+PA14.Mode=Serial_Wire
+PA14.Signal=SYS_JTCK-SWCLK
+PA2.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode
+PA2.GPIO_Label=USART_TX
+PA2.GPIO_Mode=GPIO_MODE_AF_PP
+PA2.GPIO_PuPd=GPIO_NOPULL
+PA2.GPIO_Speed=GPIO_SPEED_FREQ_LOW
+PA2.Locked=true
+PA2.Mode=Asynchronous
+PA2.Signal=USART2_TX
+PA3.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode
+PA3.GPIO_Label=USART_RX
+PA3.GPIO_Mode=GPIO_MODE_AF_PP
+PA3.GPIO_PuPd=GPIO_NOPULL
+PA3.GPIO_Speed=GPIO_SPEED_FREQ_LOW
+PA3.Locked=true
+PA3.Mode=Asynchronous
+PA3.Signal=USART2_RX
+PA5.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP
+PA5.GPIO_Label=LD2 [Green Led]
+PA5.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_PP
+PA5.GPIO_PuPd=GPIO_NOPULL
+PA5.GPIO_Speed=GPIO_SPEED_FREQ_LOW
+PA5.Locked=true
+PA5.Signal=GPIO_Output
+PB3.GPIOParameters=GPIO_Label
+PB3.GPIO_Label=SWO
+PB3.Locked=true
+PB3.Signal=SYS_JTDO-TRACESWO
+PC13-TAMPER-RTC.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
+PC13-TAMPER-RTC.GPIO_Label=B1 [Blue PushButton]
+PC13-TAMPER-RTC.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING
+PC13-TAMPER-RTC.GPIO_PuPd=GPIO_NOPULL
+PC13-TAMPER-RTC.Locked=true
+PC13-TAMPER-RTC.Signal=GPXTI13
+PC14-OSC32_IN.Locked=true
+PC14-OSC32_IN.Signal=RCC_OSC32_IN
+PC15-OSC32_OUT.Locked=true
+PC15-OSC32_OUT.Signal=RCC_OSC32_OUT
+PD0-OSC_IN.Locked=true
+PD0-OSC_IN.Signal=RCC_OSC_IN
+PD1-OSC_OUT.Locked=true
+PD1-OSC_OUT.Signal=RCC_OSC_OUT
+PinOutPanel.RotationAngle=0
+ProjectManager.AskForMigrate=true
+ProjectManager.BackupPrevious=false
+ProjectManager.CompilerOptimize=6
+ProjectManager.ComputerToolchain=false
+ProjectManager.CoupleFile=true
+ProjectManager.CustomerFirmwarePackage=
+ProjectManager.DefaultFWLocation=true
+ProjectManager.DeletePrevious=true
+ProjectManager.DeviceId=STM32F103RBTx
+ProjectManager.FirmwarePackage=STM32Cube FW_F1 V1.8.4
+ProjectManager.FreePins=false
+ProjectManager.HalAssertFull=false
+ProjectManager.HeapSize=0x200
+ProjectManager.KeepUserCode=true
+ProjectManager.LastFirmware=true
+ProjectManager.LibraryCopy=1
+ProjectManager.MainLocation=Core/Src
+ProjectManager.NoMain=false
+ProjectManager.PreviousToolchain=
+ProjectManager.ProjectBuild=false
+ProjectManager.ProjectFileName=nucleo_f103rb.ioc
+ProjectManager.ProjectName=nucleo_f103rb
+ProjectManager.RegisterCallBack=
+ProjectManager.StackSize=0x400
+ProjectManager.TargetToolchain=Other Toolchains (GPDSC)
+ProjectManager.ToolChainLocation=
+ProjectManager.UnderRoot=false
+ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-MX_DMA_Init-DMA-false-HAL-true,3-SystemClock_Config-RCC-false-HAL-false,4-MX_USART2_UART_Init-USART2-false-HAL-true
+RCC.ADCFreqValue=32000000
+RCC.AHBFreq_Value=64000000
+RCC.APB1CLKDivider=RCC_HCLK_DIV2
+RCC.APB1Freq_Value=32000000
+RCC.APB1TimFreq_Value=64000000
+RCC.APB2Freq_Value=64000000
+RCC.APB2TimFreq_Value=64000000
+RCC.FCLKCortexFreq_Value=64000000
+RCC.FamilyName=M
+RCC.HCLKFreq_Value=64000000
+RCC.IPParameters=ADCFreqValue,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLMCOFreq_Value,PLLMUL,RTCFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,TimSysFreq_Value,USBFreq_Value,VCOOutput2Freq_Value
+RCC.MCOFreq_Value=64000000
+RCC.PLLCLKFreq_Value=64000000
+RCC.PLLMCOFreq_Value=32000000
+RCC.PLLMUL=RCC_PLL_MUL16
+RCC.RTCFreq_Value=40000
+RCC.SYSCLKFreq_VALUE=64000000
+RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
+RCC.TimSysFreq_Value=64000000
+RCC.USBFreq_Value=64000000
+RCC.VCOOutput2Freq_Value=4000000
+SH.GPXTI13.0=GPIO_EXTI13
+SH.GPXTI13.ConfNb=1
+USART2.IPParameters=VirtualMode
+USART2.VirtualMode=VM_ASYNC
+VP_SYS_VS_Systick.Mode=SysTick
+VP_SYS_VS_Systick.Signal=SYS_VS_Systick
+board=NUCLEO-F103RB
+boardIOC=true
diff --git a/ci/stm32cube/ioc/nucleo_f767zi.ioc b/ci/stm32cube/ioc/nucleo_f767zi.ioc
new file mode 100644
index 00000000..aebeca36
--- /dev/null
+++ b/ci/stm32cube/ioc/nucleo_f767zi.ioc
@@ -0,0 +1,316 @@
+#MicroXplorer Configuration settings - do not modify
+Dma.Request0=USART3_RX
+Dma.Request1=USART3_TX
+Dma.RequestsNb=2
+Dma.USART3_RX.0.Direction=DMA_PERIPH_TO_MEMORY
+Dma.USART3_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE
+Dma.USART3_RX.0.Instance=DMA1_Stream1
+Dma.USART3_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE
+Dma.USART3_RX.0.MemInc=DMA_MINC_ENABLE
+Dma.USART3_RX.0.Mode=DMA_CIRCULAR
+Dma.USART3_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
+Dma.USART3_RX.0.PeriphInc=DMA_PINC_DISABLE
+Dma.USART3_RX.0.Priority=DMA_PRIORITY_VERY_HIGH
+Dma.USART3_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
+Dma.USART3_TX.1.Direction=DMA_MEMORY_TO_PERIPH
+Dma.USART3_TX.1.FIFOMode=DMA_FIFOMODE_DISABLE
+Dma.USART3_TX.1.Instance=DMA1_Stream3
+Dma.USART3_TX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE
+Dma.USART3_TX.1.MemInc=DMA_MINC_ENABLE
+Dma.USART3_TX.1.Mode=DMA_NORMAL
+Dma.USART3_TX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
+Dma.USART3_TX.1.PeriphInc=DMA_PINC_DISABLE
+Dma.USART3_TX.1.Priority=DMA_PRIORITY_VERY_HIGH
+Dma.USART3_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
+File.Version=6
+KeepUserPlacement=false
+Mcu.Family=STM32F7
+Mcu.IP0=CORTEX_M7
+Mcu.IP1=DMA
+Mcu.IP2=NVIC
+Mcu.IP3=RCC
+Mcu.IP4=SYS
+Mcu.IP5=USART3
+Mcu.IPNb=6
+Mcu.Name=STM32F767ZITx
+Mcu.Package=LQFP144
+Mcu.Pin0=PC13
+Mcu.Pin1=PC14/OSC32_IN
+Mcu.Pin10=PC5
+Mcu.Pin11=PB0
+Mcu.Pin12=PB13
+Mcu.Pin13=PB14
+Mcu.Pin14=PD8
+Mcu.Pin15=PD9
+Mcu.Pin16=PG6
+Mcu.Pin17=PG7
+Mcu.Pin18=PA8
+Mcu.Pin19=PA9
+Mcu.Pin2=PC15/OSC32_OUT
+Mcu.Pin20=PA10
+Mcu.Pin21=PA11
+Mcu.Pin22=PA12
+Mcu.Pin23=PA13
+Mcu.Pin24=PA14
+Mcu.Pin25=PG11
+Mcu.Pin26=PG13
+Mcu.Pin27=PB3
+Mcu.Pin28=PB7
+Mcu.Pin29=VP_SYS_VS_Systick
+Mcu.Pin3=PH0/OSC_IN
+Mcu.Pin4=PH1/OSC_OUT
+Mcu.Pin5=PC1
+Mcu.Pin6=PA1
+Mcu.Pin7=PA2
+Mcu.Pin8=PA7
+Mcu.Pin9=PC4
+Mcu.PinsNb=30
+Mcu.ThirdPartyNb=0
+Mcu.UserConstants=
+Mcu.UserName=STM32F767ZITx
+MxCube.Version=6.3.0
+MxDb.Version=DB.6.0.30
+NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.DMA1_Stream1_IRQn=true\:0\:0\:false\:false\:true\:false\:true
+NVIC.DMA1_Stream3_IRQn=true\:0\:0\:false\:false\:true\:false\:true
+NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.ForceEnableDMAVector=true
+NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
+NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:true\:true
+NVIC.USART3_IRQn=true\:0\:0\:false\:false\:true\:true\:true
+NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false
+PA1.GPIOParameters=GPIO_Label
+PA1.GPIO_Label=RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0]
+PA1.Locked=true
+PA1.Signal=ETH_REF_CLK
+PA10.GPIOParameters=GPIO_Label
+PA10.GPIO_Label=USB_ID
+PA10.Locked=true
+PA10.Signal=USB_OTG_FS_ID
+PA11.GPIOParameters=GPIO_Label
+PA11.GPIO_Label=USB_DM
+PA11.Locked=true
+PA11.Signal=USB_OTG_FS_DM
+PA12.GPIOParameters=GPIO_Label
+PA12.GPIO_Label=USB_DP
+PA12.Locked=true
+PA12.Signal=USB_OTG_FS_DP
+PA13.GPIOParameters=GPIO_Label
+PA13.GPIO_Label=TMS
+PA13.Locked=true
+PA13.Signal=SYS_JTMS-SWDIO
+PA14.GPIOParameters=GPIO_Label
+PA14.GPIO_Label=TCK
+PA14.Locked=true
+PA14.Signal=SYS_JTCK-SWCLK
+PA2.GPIOParameters=GPIO_Label
+PA2.GPIO_Label=RMII_MDIO [LAN8742A-CZ-TR_MDIO]
+PA2.Locked=true
+PA2.Signal=ETH_MDIO
+PA7.GPIOParameters=GPIO_Label
+PA7.GPIO_Label=RMII_CRS_DV [LAN8742A-CZ-TR_CRS_DV]
+PA7.Locked=true
+PA7.Signal=ETH_CRS_DV
+PA8.GPIOParameters=GPIO_Label
+PA8.GPIO_Label=USB_SOF [TP1]
+PA8.Locked=true
+PA8.Signal=USB_OTG_FS_SOF
+PA9.GPIOParameters=GPIO_Label
+PA9.GPIO_Label=USB_VBUS
+PA9.Locked=true
+PA9.Signal=USB_OTG_FS_VBUS
+PB0.GPIOParameters=GPIO_Label
+PB0.GPIO_Label=LD1 [Green]
+PB0.Locked=true
+PB0.Signal=GPIO_Output
+PB13.GPIOParameters=GPIO_Label
+PB13.GPIO_Label=RMII_TXD1 [LAN8742A-CZ-TR_TXD1]
+PB13.Locked=true
+PB13.Signal=ETH_TXD1
+PB14.GPIOParameters=GPIO_Label
+PB14.GPIO_Label=LD3 [Red]
+PB14.Locked=true
+PB14.Signal=GPIO_Output
+PB3.GPIOParameters=GPIO_Label
+PB3.GPIO_Label=SW0
+PB3.Locked=true
+PB3.Signal=SYS_JTDO-SWO
+PB7.GPIOParameters=GPIO_Label
+PB7.GPIO_Label=LD2 [Blue]
+PB7.Locked=true
+PB7.Signal=GPIO_Output
+PC1.GPIOParameters=GPIO_Label
+PC1.GPIO_Label=RMII_MDC [LAN8742A-CZ-TR_MDC]
+PC1.Locked=true
+PC1.Signal=ETH_MDC
+PC13.GPIOParameters=GPIO_Label
+PC13.GPIO_Label=USER_Btn [B1]
+PC13.Locked=true
+PC13.Signal=GPXTI13
+PC14/OSC32_IN.Locked=true
+PC14/OSC32_IN.Signal=RCC_OSC32_IN
+PC15/OSC32_OUT.Locked=true
+PC15/OSC32_OUT.Signal=RCC_OSC32_OUT
+PC4.GPIOParameters=GPIO_Label
+PC4.GPIO_Label=RMII_RXD0 [LAN8742A-CZ-TR_RXD0]
+PC4.Locked=true
+PC4.Signal=ETH_RXD0
+PC5.GPIOParameters=GPIO_Label
+PC5.GPIO_Label=RMII_RXD1 [LAN8742A-CZ-TR_RXD1]
+PC5.Locked=true
+PC5.Signal=ETH_RXD1
+PD8.GPIOParameters=GPIO_Label
+PD8.GPIO_Label=STLK_RX [STM32F103CBT6_PA3]
+PD8.Locked=true
+PD8.Mode=Asynchronous
+PD8.Signal=USART3_TX
+PD9.GPIOParameters=GPIO_Label
+PD9.GPIO_Label=STLK_TX [STM32F103CBT6_PA2]
+PD9.Locked=true
+PD9.Mode=Asynchronous
+PD9.Signal=USART3_RX
+PG11.GPIOParameters=GPIO_Label
+PG11.GPIO_Label=RMII_TX_EN [LAN8742A-CZ-TR_TXEN]
+PG11.Locked=true
+PG11.Signal=ETH_TX_EN
+PG13.GPIOParameters=GPIO_Label
+PG13.GPIO_Label=RMII_TXD0 [LAN8742A-CZ-TR_TXD0]
+PG13.Locked=true
+PG13.Signal=ETH_TXD0
+PG6.GPIOParameters=GPIO_Label
+PG6.GPIO_Label=USB_PowerSwitchOn [STMPS2151STR_EN]
+PG6.Locked=true
+PG6.Signal=GPIO_Output
+PG7.GPIOParameters=GPIO_Label
+PG7.GPIO_Label=USB_OverCurrent [STMPS2151STR_FAULT]
+PG7.Locked=true
+PG7.Signal=GPIO_Input
+PH0/OSC_IN.GPIOParameters=GPIO_Label
+PH0/OSC_IN.GPIO_Label=MCO [STM32F103CBT6_PA8]
+PH0/OSC_IN.Locked=true
+PH0/OSC_IN.Signal=RCC_OSC_IN
+PH1/OSC_OUT.Locked=true
+PH1/OSC_OUT.Signal=RCC_OSC_OUT
+PinOutPanel.RotationAngle=0
+ProjectManager.AskForMigrate=true
+ProjectManager.BackupPrevious=false
+ProjectManager.CompilerOptimize=6
+ProjectManager.ComputerToolchain=false
+ProjectManager.CoupleFile=true
+ProjectManager.CustomerFirmwarePackage=
+ProjectManager.DefaultFWLocation=true
+ProjectManager.DeletePrevious=true
+ProjectManager.DeviceId=STM32F767ZITx
+ProjectManager.FirmwarePackage=STM32Cube FW_F7 V1.16.2
+ProjectManager.FreePins=false
+ProjectManager.HalAssertFull=false
+ProjectManager.HeapSize=0x200
+ProjectManager.KeepUserCode=true
+ProjectManager.LastFirmware=true
+ProjectManager.LibraryCopy=1
+ProjectManager.MainLocation=Core/Src
+ProjectManager.NoMain=false
+ProjectManager.PreviousToolchain=
+ProjectManager.ProjectBuild=false
+ProjectManager.ProjectFileName=nucleo_f767zi.ioc
+ProjectManager.ProjectName=nucleo_f767zi
+ProjectManager.RegisterCallBack=
+ProjectManager.StackSize=0x400
+ProjectManager.TargetToolchain=Other Toolchains (GPDSC)
+ProjectManager.ToolChainLocation=
+ProjectManager.UnderRoot=false
+ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_USART3_UART_Init-USART3-false-HAL-true,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true
+RCC.48MHZClocksFreq_Value=24000000
+RCC.ADC12outputFreq_Value=72000000
+RCC.ADC34outputFreq_Value=72000000
+RCC.AHBFreq_Value=16000000
+RCC.APB1CLKDivider=RCC_HCLK_DIV2
+RCC.APB1Freq_Value=8000000
+RCC.APB1TimFreq_Value=16000000
+RCC.APB2Freq_Value=16000000
+RCC.APB2TimFreq_Value=16000000
+RCC.CECFreq_Value=32786.88524590164
+RCC.CortexFreq_Value=16000000
+RCC.DFSDMFreq_Value=16000000
+RCC.EthernetFreq_Value=16000000
+RCC.FCLKCortexFreq_Value=16000000
+RCC.FamilyName=M
+RCC.HCLKFreq_Value=16000000
+RCC.HSE_VALUE=16000000
+RCC.HSI_VALUE=16000000
+RCC.I2C1Freq_Value=8000000
+RCC.I2C2Freq_Value=8000000
+RCC.I2C3Freq_Value=8000000
+RCC.I2C4Freq_Value=8000000
+RCC.I2SClocksFreq_Value=48000000
+RCC.I2SFreq_Value=96000000
+RCC.IPParameters=48MHZClocksFreq_Value,ADC12outputFreq_Value,ADC34outputFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,CECFreq_Value,CortexFreq_Value,DFSDMFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2C3Freq_Value,I2C4Freq_Value,I2SClocksFreq_Value,I2SFreq_Value,LCDTFTFreq_Value,LCDTFToutputFreq_Value,LPTIM1Freq_Value,LSE_VALUE,LSI_VALUE,MCO1PinFreq_Value,MCO2PinFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLI2SPCLKFreq_Value,PLLI2SQCLKFreq_Value,PLLI2SRCLKFreq_Value,PLLI2SRoutputFreq_Value,PLLMCOFreq_Value,PLLMUL,PLLQCLKFreq_Value,PLLQoutputFreq_Value,PLLSAIPCLKFreq_Value,PLLSAIQCLKFreq_Value,PLLSAIRCLKFreq_Value,PLLSAIoutputFreq_Value,PRESCALERUSB,RNGFreq_Value,RTCFreq_Value,RTCHSEDivFreq_Value,SAI1Freq_Value,SAI2Freq_Value,SDMMC2Freq_Value,SDMMCFreq_Value,SPDIFRXFreq_Value,SYSCLKFreq_VALUE,SYSCLKSourceVirtual,TIM15Freq_Value,TIM16Freq_Value,TIM17Freq_Value,TIM1Freq_Value,TIM20Freq_Value,TIM2Freq_Value,TIM3Freq_Value,TIM8Freq_Value,UART4Freq_Value,UART5Freq_Value,UART7Freq_Value,UART8Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USART6Freq_Value,USBFreq_Value,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutput2Freq_Value,VCOOutputFreq_Value,VCOSAIOutputFreq_Value,VcooutputI2S,WatchDogFreq_Value
+RCC.LCDTFTFreq_Value=48000000
+RCC.LCDTFToutputFreq_Value=24000000
+RCC.LPTIM1Freq_Value=8000000
+RCC.LSE_VALUE=32768
+RCC.LSI_VALUE=32000
+RCC.MCO1PinFreq_Value=16000000
+RCC.MCO2PinFreq_Value=16000000
+RCC.MCOFreq_Value=72000000
+RCC.PLLCLKFreq_Value=96000000
+RCC.PLLI2SPCLKFreq_Value=96000000
+RCC.PLLI2SQCLKFreq_Value=96000000
+RCC.PLLI2SRCLKFreq_Value=96000000
+RCC.PLLI2SRoutputFreq_Value=96000000
+RCC.PLLMCOFreq_Value=72000000
+RCC.PLLMUL=RCC_PLL_MUL9
+RCC.PLLQCLKFreq_Value=96000000
+RCC.PLLQoutputFreq_Value=96000000
+RCC.PLLSAIPCLKFreq_Value=96000000
+RCC.PLLSAIQCLKFreq_Value=96000000
+RCC.PLLSAIRCLKFreq_Value=96000000
+RCC.PLLSAIoutputFreq_Value=96000000
+RCC.PRESCALERUSB=RCC_USBCLKSOURCE_PLL_DIV1_5
+RCC.RNGFreq_Value=96000000
+RCC.RTCFreq_Value=32000
+RCC.RTCHSEDivFreq_Value=4000000
+RCC.SAI1Freq_Value=96000000
+RCC.SAI2Freq_Value=96000000
+RCC.SDMMC2Freq_Value=16000000
+RCC.SDMMCFreq_Value=16000000
+RCC.SPDIFRXFreq_Value=96000000
+RCC.SYSCLKFreq_VALUE=16000000
+RCC.SYSCLKSourceVirtual=RCC_SYSCLKSOURCE_PLLCLK
+RCC.TIM15Freq_Value=72000000
+RCC.TIM16Freq_Value=72000000
+RCC.TIM17Freq_Value=72000000
+RCC.TIM1Freq_Value=72000000
+RCC.TIM20Freq_Value=72000000
+RCC.TIM2Freq_Value=72000000
+RCC.TIM3Freq_Value=72000000
+RCC.TIM8Freq_Value=72000000
+RCC.UART4Freq_Value=8000000
+RCC.UART5Freq_Value=8000000
+RCC.UART7Freq_Value=8000000
+RCC.UART8Freq_Value=8000000
+RCC.USART1Freq_Value=16000000
+RCC.USART2Freq_Value=8000000
+RCC.USART3Freq_Value=8000000
+RCC.USART6Freq_Value=16000000
+RCC.USBFreq_Value=96000000
+RCC.VCOI2SOutputFreq_Value=192000000
+RCC.VCOInputFreq_Value=1000000
+RCC.VCOOutput2Freq_Value=8000000
+RCC.VCOOutputFreq_Value=192000000
+RCC.VCOSAIOutputFreq_Value=192000000
+RCC.VcooutputI2S=48000000
+RCC.WatchDogFreq_Value=32000
+SH.GPXTI13.0=GPIO_EXTI13
+SH.GPXTI13.ConfNb=1
+USART3.IPParameters=VirtualMode-Asynchronous
+USART3.VirtualMode-Asynchronous=VM_ASYNC
+VP_SYS_VS_Systick.Mode=SysTick
+VP_SYS_VS_Systick.Signal=SYS_VS_Systick
+board=NUCLEO-F767ZI
+boardIOC=true
diff --git a/ci/stm32cube/platformio.ini b/ci/stm32cube/platformio.ini
new file mode 100644
index 00000000..c1d02fe5
--- /dev/null
+++ b/ci/stm32cube/platformio.ini
@@ -0,0 +1,24 @@
+[env]
+platform = ststm32@15.4.1
+framework = stm32cube
+board_build.stm32cube.custom_config_header = yes
+lib_deps =
+ ../../
+
+[env:nucleo_f103rb]
+board = nucleo_f103rb
+board_microros_transport = serial
+build_flags=
+ -DSTM32F1xx
+ -DUART_HANDLE=huart2
+
+[env:nucleo_f767zi]
+board = nucleo_f767zi
+board_microros_transport = serial
+build_flags=
+ -DSTM32F7xx
+ -DUART_HANDLE=huart3
+
+[platformio]
+include_dir = Inc
+src_dir = Src
diff --git a/ci/stm32cube/stm32pio.ini b/ci/stm32cube/stm32pio.ini
new file mode 100644
index 00000000..31a02250
--- /dev/null
+++ b/ci/stm32cube/stm32pio.ini
@@ -0,0 +1,2 @@
+[app]
+cubemx_cmd = /usr/local/STMicroelectronics/STM32Cube/STM32CubeMX/STM32CubeMX
diff --git a/extra_script.py b/extra_script.py
index 33700b9f..6da026d3 100644
--- a/extra_script.py
+++ b/extra_script.py
@@ -21,8 +21,9 @@
"olimex_e407" : "colcon.meta",
"due" : "colcon_verylowmem.meta",
"zero" : "colcon_verylowmem.meta",
- "pico": "colcon.meta"
-
+ "pico": "colcon.meta",
+ "nucleo_f103rb": "colcon_verylowmem.meta",
+ "nucleo_f767zi": "colcon.meta"
}
project_options = env.GetProjectConfig().items(env=env["PIOENV"], as_dict=True)
diff --git a/library.json b/library.json
index 2ca60302..53775d16 100755
--- a/library.json
+++ b/library.json
@@ -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"
}
\ No newline at end of file
diff --git a/platform_code/stm32cube/clock_gettime.cpp b/platform_code/stm32cube/clock_gettime.cpp
new file mode 100644
index 00000000..4db69a8a
--- /dev/null
+++ b/platform_code/stm32cube/clock_gettime.cpp
@@ -0,0 +1,36 @@
+#include
+
+#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;
+
+ __disable_irq();
+ uint32_t m = HAL_GetTick();
+ rollover += (m < last_measure) ? 1 : 0;
+ last_measure = m;
+ __enable_irq();
+
+ uint64_t real_us =
+ static_cast(m) * 1000UL + rollover * GETTICK_ROLLOVER_USECONDS;
+ tp->tv_sec = real_us / 1000000;
+ tp->tv_nsec = (real_us % 1000000) * 1000;
+
+ return 0;
+}
diff --git a/platform_code/stm32cube/custom/micro_ros_transport.h b/platform_code/stm32cube/custom/micro_ros_transport.h
new file mode 100644
index 00000000..e69de29b
diff --git a/platform_code/stm32cube/serial/micro_ros_transport.cpp b/platform_code/stm32cube/serial/micro_ros_transport.cpp
new file mode 100644
index 00000000..a68b27d5
--- /dev/null
+++ b/platform_code/stm32cube/serial/micro_ros_transport.cpp
@@ -0,0 +1,104 @@
+#include
+
+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;
+ 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++;
+
+ 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;
+
+ 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();
+
+ if (rhead != rtail || 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;
+ }
+
+ return wrote;
+}
+}
\ No newline at end of file
diff --git a/platform_code/stm32cube/serial/micro_ros_transport.h b/platform_code/stm32cube/serial/micro_ros_transport.h
new file mode 100644
index 00000000..2922788b
--- /dev/null
+++ b/platform_code/stm32cube/serial/micro_ros_transport.h
@@ -0,0 +1,50 @@
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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 handle to use for transport.
+ UART_HandleTypeDef* uart;
+
+ /// Size of the read buffer, must be a power of 2.
+ uint16_t rbuffer_size;
+
+ /// Pointer to read buffer.
+ uint8_t* rbuffer;
+
+ /// Size of the transmit buffer, must be a power of 2.
+ uint16_t tbuffer_size;
+
+ /// Pointer to transmit buffer.
+ uint8_t* tbuffer;
+};
+
+static inline void set_microros_serial_transports(struct DMAStream* stream) {
+ rmw_uros_set_custom_transport(
+ true, stream, platformio_transport_open, platformio_transport_close,
+ platformio_transport_write, platformio_transport_read);
+}
+
+/// This function should be called from HAL_UART_TxCpltCallback. Otherwise the
+/// transform won't work properly.
+void uart_transfer_complete_callback(struct DMAStream* stream);
+
+#ifdef __cplusplus
+}
+#endif