Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
71 changes: 2 additions & 69 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,75 +18,8 @@ if (CONFIG_ARDUINO_API)
zephyr_include_directories(${variant_dir})

if (CONFIG_USE_ARDUINO_API_RUST_IMPLEMENTATION)
# quote from https://github.com/zephyrproject-rtos/zephyr-lang-rust/blob/main/CMakeLists.txt
function (rust_target_arch RUST_TARGET)
# Map Zephyr targets to LLVM targets.
if(CONFIG_CPU_CORTEX_M)
if(CONFIG_CPU_CORTEX_M0 OR CONFIG_CPU_CORTEX_M0PLUS OR CONFIG_CPU_CORTEX_M1)
set(${RUST_TARGET} "thumbv6m-none-eabi" PARENT_SCOPE)
elseif(CONFIG_CPU_CORTEX_M3)
set(${RUST_TARGET} "thumbv7m-none-eabi" PARENT_SCOPE)
elseif(CONFIG_CPU_CORTEX_M4 OR CONFIG_CPU_CORTEX_M7)
if(CONFIG_FP_HARDABI OR FORCE_FP_HARDABI)
set(${RUST_TARGET} "thumbv7em-none-eabihf" PARENT_SCOPE)
else()
set(${RUST_TARGET} "thumbv7em-none-eabi" PARENT_SCOPE)
endif()
elseif(CONFIG_CPU_CORTEX_M23)
set(${RUST_TARGET} "thumbv8m.base-none-eabi" PARENT_SCOPE)
elseif(CONFIG_CPU_CORTEX_M33 OR CONFIG_CPU_CORTEX_M55)
# Not a typo, Zephyr, uses ARMV7_M_ARMV8_M_FP to select the FP even on v8m.
if(CONFIG_FP_HARDABI OR FORCE_FP_HARDABI)
set(${RUST_TARGET} "thumbv8m.main-none-eabihf" PARENT_SCOPE)
else()
set(${RUST_TARGET} "thumbv8m.main-none-eabi" PARENT_SCOPE)
endif()

# Todo: The M55 is thumbv8.1m.main-none-eabi, which can be added when Rust
# gain support for this target.
else()
message(FATAL_ERROR "Unknown Cortex-M target.")
endif()
elseif(CONFIG_RISCV)
if(CONFIG_RISCV_ISA_RV64I)
# TODO: Should fail if the extensions don't match.
set(${RUST_TARGET} "riscv64imac-unknown-none-elf" PARENT_SCOPE)
elseif(CONFIG_RISCV_ISA_RV32I)
# TODO: We have multiple choices, try to pick the best.
set(${RUST_TARGET} "riscv32i-unknown-none-elf" PARENT_SCOPE)
else()
message(FATAL_ERROR "Rust: Unsupported riscv ISA")
endif()
elseif(CONFIG_ARCH_POSIX AND CONFIG_64BIT AND (${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "x86_64"))
set(${RUST_TARGET} "x86_64-unknown-none" PARENT_SCOPE)
elseif(CONFIG_ARCH_POSIX AND CONFIG_64BIT AND (${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "aarch64"))
set(${RUST_TARGET} "aarch64-unknown-none" PARENT_SCOPE)
else()
message(FATAL_ERROR "Rust: Add support for other target")
endif()
endfunction()

rust_target_arch(RUST_TARGET_TRIPLE)

set(RUST_CRATE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/rust)
set(RUST_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/rust)
set(RUST_LIB ${RUST_OUT_DIR}/target/${RUST_TARGET_TRIPLE}/release/libarduinocore_api_rust.a)

add_custom_command(
OUTPUT ${RUST_LIB}
COMMAND ${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${RUST_OUT_DIR}/target
cargo build --manifest-path ${RUST_CRATE_DIR}/Cargo.toml
--target ${RUST_TARGET_TRIPLE} --release
WORKING_DIRECTORY ${RUST_CRATE_DIR}
COMMENT "Building Rust staticlib for ${RUST_TARGET}"
VERBATIM
)

add_custom_target(arduinocore_api_rust_build ALL DEPENDS ${RUST_LIB})
add_library(arduinocore_api_rust STATIC IMPORTED GLOBAL)
set_target_properties(arduinocore_api_rust PROPERTIES IMPORTED_LOCATION ${RUST_LIB})
zephyr_link_libraries(arduinocore_api_rust)
zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/zephyr/blobs/ArduinoCore-API/)
zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/alt_arduinocore_api)
add_subdirectory(alt_arduinocore_api)
else()
zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/zephyr/blobs/ArduinoCore-API/)
zephyr_sources(${CMAKE_CURRENT_SOURCE_DIR}/zephyr/blobs/ArduinoCore-API/api/CanMsg.cpp)
Expand Down
1 change: 1 addition & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ if ARDUINO_API
config USE_ARDUINO_API_RUST_IMPLEMENTATION
bool "Use Rust implementation API core"
select RUST
select NANOPB

config QEMU_ICOUNT
bool "QEMU icount mode"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The **Arduino Core API** module for zephyr leverages the power of Zephyr under a

* [Using external Arduino Libraries](/documentation/arduino_libs.md)
* [Adding custom boards/ variants](/documentation/variants.md)
* [Arduino IDL code generation](/documentation/idl_codegen.md)

## Adding Arduino Core API to Zephyr

Expand Down
83 changes: 83 additions & 0 deletions alt_arduinocore_api/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# SPDX-License-Identifier: Apache-2.0

function(rust_target_arch RUST_TARGET)
# Map Zephyr targets to LLVM targets.
if(CONFIG_CPU_CORTEX_M)
if(CONFIG_CPU_CORTEX_M0 OR CONFIG_CPU_CORTEX_M0PLUS OR CONFIG_CPU_CORTEX_M1)
set(${RUST_TARGET} "thumbv6m-none-eabi" PARENT_SCOPE)
elseif(CONFIG_CPU_CORTEX_M3)
set(${RUST_TARGET} "thumbv7m-none-eabi" PARENT_SCOPE)
elseif(CONFIG_CPU_CORTEX_M4 OR CONFIG_CPU_CORTEX_M7)
if(CONFIG_FP_HARDABI OR FORCE_FP_HARDABI)
set(${RUST_TARGET} "thumbv7em-none-eabihf" PARENT_SCOPE)
else()
set(${RUST_TARGET} "thumbv7em-none-eabi" PARENT_SCOPE)
endif()
elseif(CONFIG_CPU_CORTEX_M23)
set(${RUST_TARGET} "thumbv8m.base-none-eabi" PARENT_SCOPE)
elseif(CONFIG_CPU_CORTEX_M33 OR CONFIG_CPU_CORTEX_M55)
if(CONFIG_FP_HARDABI OR FORCE_FP_HARDABI)
set(${RUST_TARGET} "thumbv8m.main-none-eabihf" PARENT_SCOPE)
else()
set(${RUST_TARGET} "thumbv8m.main-none-eabi" PARENT_SCOPE)
endif()
else()
message(FATAL_ERROR "Unknown Cortex-M target.")
endif()
elseif(CONFIG_RISCV)
if(CONFIG_RISCV_ISA_RV64I)
set(${RUST_TARGET} "riscv64imac-unknown-none-elf" PARENT_SCOPE)
elseif(CONFIG_RISCV_ISA_RV32I)
set(${RUST_TARGET} "riscv32i-unknown-none-elf" PARENT_SCOPE)
else()
message(FATAL_ERROR "Rust: Unsupported riscv ISA")
endif()
elseif(CONFIG_ARCH_POSIX AND CONFIG_64BIT AND (${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "x86_64"))
set(${RUST_TARGET} "x86_64-unknown-none" PARENT_SCOPE)
elseif(CONFIG_ARCH_POSIX AND CONFIG_64BIT AND (${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "aarch64"))
set(${RUST_TARGET} "aarch64-unknown-none" PARENT_SCOPE)
else()
message(FATAL_ERROR "Rust: Add support for other target")
endif()
endfunction()

rust_target_arch(RUST_TARGET_TRIPLE)

if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/rust/Cargo.toml)
set(RUST_CRATE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/rust)
else()
set(RUST_CRATE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../rust)
endif()
set(RUST_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/rust)
set(RUST_LIB ${RUST_OUT_DIR}/target/${RUST_TARGET_TRIPLE}/release/libarduinocore_api_rust.a)
set(RUST_SRCS
${RUST_CRATE_DIR}/src/lib.rs
${RUST_CRATE_DIR}/src/common.rs
${RUST_CRATE_DIR}/src/string.rs
)

add_custom_command(
OUTPUT ${RUST_LIB}
COMMAND ${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${RUST_OUT_DIR}/target
cargo build --manifest-path ${RUST_CRATE_DIR}/Cargo.toml
--target ${RUST_TARGET_TRIPLE} --release
WORKING_DIRECTORY ${RUST_CRATE_DIR}
DEPENDS ${RUST_CRATE_DIR}/Cargo.toml ${RUST_SRCS}
COMMENT "Building Rust staticlib for ${RUST_TARGET_TRIPLE}"
VERBATIM
)

add_custom_target(arduinocore_api_rust_build ALL DEPENDS ${RUST_LIB})
add_library(arduinocore_api_rust STATIC IMPORTED GLOBAL)
set_target_properties(arduinocore_api_rust PROPERTIES IMPORTED_LOCATION ${RUST_LIB})
zephyr_link_libraries(arduinocore_api_rust)

if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/idl/CMakeLists.txt)
add_subdirectory(idl)
elseif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../idl/CMakeLists.txt)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../idl ${CMAKE_CURRENT_BINARY_DIR}/legacy_idl)
endif()

if(TARGET arduinocore_idl_generate_interfaces)
add_dependencies(app arduinocore_idl_generate_interfaces)
endif()
130 changes: 130 additions & 0 deletions alt_arduinocore_api/api/ArduinoAPI.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#pragma once

#ifdef __cplusplus
#include <cstdint>
#include <cstddef>
#include <stdlib.h>
#else
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#endif
#include <zephyr/drivers/gpio.h>

#include "api/HardwareSerial.h"
#include "common_types.h"

#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))

#define bit(b) BIT(b)
#define bitRead(value, bit) FIELD_GET(BIT(bit), value)
#define bitSet(value, bit) ((value) |= BIT(bit))
#define bitClear(value, bit) ((value) &= ~BIT(bit))
#define bitToggle(value, bit) ((value) ^= BIT(bit))
#define bitWrite(value, bit, bitvalue) WRITE_BIT(value, bit, bitvalue)


#ifdef __cplusplus
extern "C" {
#endif

typedef gpio_port_pins_t pin_size_t;

typedef void (*voidFuncPtr)(void);
typedef void (*voidFuncPtrParam)(void*);

void yield(void);

void init(void);
void initVariant(void);

int main() __attribute__((weak));

void pinMode(pin_size_t pinNumber, PinMode pinMode);
void digitalWrite(pin_size_t pinNumber, PinStatus status);
PinStatus digitalRead(pin_size_t pinNumber);
int analogRead(pin_size_t pinNumber);
void analogReference(uint8_t mode);
void analogWrite(pin_size_t pinNumber, int value);

unsigned long millis(void);
unsigned long micros(void);
void delay(unsigned long);
void delayMicroseconds(unsigned int us);
unsigned long pulseIn(pin_size_t pin, uint8_t state, unsigned long timeout);
unsigned long pulseInLong(pin_size_t pin, uint8_t state, unsigned long timeout);

void shiftOut(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder, uint8_t val);
uint8_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder);

void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode);
void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void* param);
void detachInterrupt(pin_size_t interruptNumber);

void setup(void);
void loop(void);

#ifdef __cplusplus
} // extern "C"
#endif

unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);

void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
void noTone(uint8_t _pin);

// WMath prototypes
long random(long);
long random(long, long);
void randomSeed(unsigned long);


extern "C" {
int32_t map_i32(int32_t x, int32_t in_min, int32_t in_max, int32_t out_min, int32_t out_max);
uint16_t makeWord_w(uint16_t w);
uint16_t makeWord_hl(uint8_t h, uint8_t l);
}

inline long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return map_i32(x, in_min, in_max, out_min, out_max);
}

inline uint16_t makeWord(uint16_t w) {
return makeWord_w(w);
}

inline uint16_t makeWord(uint8_t h, uint8_t l) {
return makeWord_hl(h, l);
}

#define word(...) makeWord(__VA_ARGS__)

#ifdef __cplusplus
template<class T, class L>
auto min(const T& a, const L& b) -> decltype((b < a) ? b : a)
{
return (b < a) ? b : a;
}

template<class T, class L>
auto max(const T& a, const L& b) -> decltype((b < a) ? b : a)
{
return (a < b) ? b : a;
}
#else
#ifndef min
#define min(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
#endif
#ifndef max
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
#endif
#endif
7 changes: 7 additions & 0 deletions alt_arduinocore_api/api/Binary.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* Copyright (c) 2026 TOKITA Hiroshi
*
* SPDX-License-Identifier: Apache-2.0
*/

/* stub file for compat */
13 changes: 13 additions & 0 deletions alt_arduinocore_api/api/Client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Missing copyright and SPDX license header. All other new files in this PR have proper copyright headers with "Copyright (c) 2026 TOKITA Hiroshi" and "SPDX-License-Identifier: Apache-2.0".

Copilot uses AI. Check for mistakes.

#include "Stream.h"
#include <client_interface.hpp>

namespace arduino {

class Client : virtual public Stream, virtual public ClientInterface {
protected:
uint8_t* rawIPAddress(IPAddress& addr); //TODO
};
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Missing semicolon after the closing brace of the class definition. Comparing to other files like Server.h (line 16), Stream.h (line 15), and Printable.h (line 18), all class definitions should end with a semicolon.

Copilot uses AI. Check for mistakes.

};
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Missing closing namespace comment. Line 14 closes namespace arduino { but there's no comment indicating which namespace is being closed. For consistency with other files (like HardwareI2C.h line 18), consider adding a comment like }; // namespace arduino.

Suggested change
};
}; // namespace arduino

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Missing newline at end of file. This violates POSIX standards and can cause issues with some tools.

Copilot uses AI. Check for mistakes.
7 changes: 7 additions & 0 deletions alt_arduinocore_api/api/Common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* Copyright (c) 2026 TOKITA Hiroshi
*
* SPDX-License-Identifier: Apache-2.0
*/

/* stub file for compat */
17 changes: 17 additions & 0 deletions alt_arduinocore_api/api/HardwareI2C.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright (c) 2026 TOKITA Hiroshi
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include "Stream.h"
#include <hardware_i2c_interface.hpp>

namespace arduino {

class HardwareI2C : virtual public Stream, virtual public HardwareI2CInterface {
};

};
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Missing newline at end of file. This violates POSIX standards and can cause issues with some tools.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Missing semicolon after the closing brace of the class declaration. This will cause a compilation error.

Suggested change
};
}

Copilot uses AI. Check for mistakes.
18 changes: 18 additions & 0 deletions alt_arduinocore_api/api/HardwareSPI.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright (c) 2026 TOKITA Hiroshi
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include "Stream.h"
#include <hardware_spi_interface.hpp>

namespace arduino {

class HardwareSPI : virtual public HardwareSPIInterface {
};

typedef HardwareSPI SPIClass;
};
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Inconsistent semicolon usage in namespace closing. Line 14 has }; but line 18 has }; - both close namespaces but neither has a comment identifying which namespace. For consistency with other files (like HardwareI2C.h line 18), consider adding namespace comments.

Suggested change
};
} // namespace arduino

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Missing newline at end of file. This violates POSIX standards and can cause issues with some tools.

Suggested change
};
};

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Missing semicolon after the closing brace of the class declaration. This will cause a compilation error.

Suggested change
};
}

Copilot uses AI. Check for mistakes.
Loading
Loading