start of rust + c journey
This commit is contained in:
parent
b4bba1e5cc
commit
76f1651736
|
|
@ -2,6 +2,8 @@
|
||||||
build/
|
build/
|
||||||
target/
|
target/
|
||||||
|
|
||||||
|
.direnv
|
||||||
|
|
||||||
sdkconfig.old
|
sdkconfig.old
|
||||||
sdkconfig
|
sdkconfig
|
||||||
debug/
|
debug/
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit ede403613d96b3233e2c8f8be04dc4cb9efd7569
|
Subproject commit 8ae1b54c6100a96a670255e35960f9372c2b4dfb
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
|
|
||||||
idf_component_register(
|
|
||||||
SRCS "placeholder.c"
|
|
||||||
INCLUDE_DIRS ""
|
|
||||||
PRIV_REQUIRES "${RUST_DEPS}"
|
|
||||||
)
|
|
||||||
|
|
||||||
set(CARGO_BUILD_TYPE "release")
|
|
||||||
set(CARGO_BUILD_ARG "--release")
|
|
||||||
if(CONFIG_IDF_TARGET_ARCH_RISCV)
|
|
||||||
set(CARGO_TARGET "riscv32imc-esp-espidf")
|
|
||||||
set(CARGO_FEATURES_ARG "")
|
|
||||||
elseif(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
|
||||||
set(CARGO_TARGET "xtensa-esp32-espidf")
|
|
||||||
set(CARGO_FEATURES_ARG "--features=std")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(RUST_PROJECT_DIR "${CMAKE_CURRENT_LIST_DIR}")
|
|
||||||
set(RUST_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
|
||||||
set(RUST_TARGET_DIR "${RUST_BUILD_DIR}/target")
|
|
||||||
set(RUST_INCLUDE_DIR "${RUST_TARGET_DIR}")
|
|
||||||
set(RUST_INCLUDE_HEADER "${RUST_INCLUDE_DIR}/RustApi.h")
|
|
||||||
set(RUST_STATIC_LIBRARY "${RUST_TARGET_DIR}/${CARGO_TARGET}/${CARGO_BUILD_TYPE}/librustlib.a")
|
|
||||||
|
|
||||||
idf_build_get_property(sdkconfig SDKCONFIG)
|
|
||||||
|
|
||||||
ExternalProject_Add(
|
|
||||||
rustlib_project
|
|
||||||
PREFIX "${RUST_PROJECT_DIR}"
|
|
||||||
DOWNLOAD_COMMAND ""
|
|
||||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env
|
|
||||||
CARGO_BUILD_TARGET=${CARGO_TARGET}
|
|
||||||
CARGO_BUILD_TARGET_DIR=${RUST_TARGET_DIR}
|
|
||||||
cargo clean
|
|
||||||
BUILD_COMMAND ${CMAKE_COMMAND} -E env
|
|
||||||
CARGO_BUILD_TARGET=${CARGO_TARGET}
|
|
||||||
CARGO_BUILD_TARGET_DIR=${RUST_TARGET_DIR}
|
|
||||||
CARGO_CMAKE_BUILD_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_LIB},INCLUDE_DIRECTORIES>
|
|
||||||
CARGO_CMAKE_BUILD_LINK_LIBRARIES=$<TARGET_PROPERTY:${COMPONENT_LIB},LINK_LIBRARIES>
|
|
||||||
CARGO_CMAKE_BUILD_SDKCONFIG=${sdkconfig}
|
|
||||||
CARGO_CMAKE_BUILD_COMPILER=${CMAKE_C_COMPILER}
|
|
||||||
cargo build ${CARGO_BUILD_ARG} ${CARGO_FEATURES_ARG}
|
|
||||||
INSTALL_COMMAND ""
|
|
||||||
BUILD_ALWAYS TRUE
|
|
||||||
TMP_DIR "${RUST_BUILD_DIR}/tmp"
|
|
||||||
STAMP_DIR "${RUST_BUILD_DIR}/stamp"
|
|
||||||
DOWNLOAD_DIR "${RUST_BUILD_DIR}"
|
|
||||||
SOURCE_DIR "${RUST_PROJECT_DIR}"
|
|
||||||
BINARY_DIR "${RUST_PROJECT_DIR}"
|
|
||||||
INSTALL_DIR "${RUST_BUILD_DIR}"
|
|
||||||
BUILD_BYPRODUCTS
|
|
||||||
"${RUST_INCLUDE_HEADER}"
|
|
||||||
"${RUST_STATIC_LIBRARY}"
|
|
||||||
)
|
|
||||||
|
|
||||||
set_source_files_properties("${RUST_INCLUDE_HEADER}" PROPERTIES GENERATED true)
|
|
||||||
|
|
||||||
add_prebuilt_library(rustlib_lib "${RUST_STATIC_LIBRARY}" PRIV_REQUIRES "${RUST_DEPS}")
|
|
||||||
add_dependencies(rustlib_lib rustlib_project)
|
|
||||||
|
|
||||||
target_include_directories(${COMPONENT_LIB} PUBLIC "${RUST_INCLUDE_DIR}")
|
|
||||||
target_link_libraries(${COMPONENT_LIB} PRIVATE rustlib_lib)
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "rustlib"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Espressif Systems CO LTD", "June Life Inc"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
crate-type = ["staticlib"]
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
bindgen = "0.58"
|
|
||||||
cbindgen = "0.19"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
std = []
|
|
||||||
|
|
||||||
[profile.dev]
|
|
||||||
# Optimization level 1 is similar to "g" in gcc/clang, although for some reason
|
|
||||||
# Cargo doesn't support that flag.
|
|
||||||
#opt-level = 1
|
|
||||||
opt-level = "s"
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
debug = true
|
|
||||||
opt-level = "z"
|
|
||||||
#debug = true
|
|
||||||
#lto = true
|
|
||||||
#opt-level = "z"
|
|
||||||
#codegen-units = 1
|
|
||||||
#panic = "abort"
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
# rustlib
|
|
||||||
|
|
||||||
This component generates a static library from Rust source code and exposes functions that will be callable from the main IDF application from C.
|
|
||||||
|
|
||||||
This component is responsible for three separate functions:
|
|
||||||
|
|
||||||
* Export C bindings for Rust functions with `cbindgen`.
|
|
||||||
* Import Rust binding for C functions with `bindgen`.
|
|
||||||
* Build a top level static library from Rust code. The `cargo` build command is wrapped in a CMake `ExternalProject_Add` command.
|
|
||||||
|
|
||||||
Currently the `build.rs` script expects the `clib` component to export a header with the name `CApi.h`. If the name of the include file changes or if more files are added, the build script must be updated to process the latest headers.
|
|
||||||
|
|
||||||
Depending on the complexity of the project, the `cbindgen` and `bindgen` steps could be broken out into one or more IDF components or Rust crates. However, to prevent redundant duplication of the Rust runtime, all Rust crates should be compiled into a single static library that will be linked into the final IDF application.
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
use std::env;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let cargo_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
|
|
||||||
let target_dir = PathBuf::from(env::var("CARGO_BUILD_TARGET_DIR").unwrap());
|
|
||||||
|
|
||||||
run_cbindgen(&cargo_dir, &target_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_cbindgen(cargo_dir: &Path, target_dir: &Path) {
|
|
||||||
let out = target_dir.join("RustApi.h");
|
|
||||||
|
|
||||||
cbindgen::Builder::new()
|
|
||||||
.with_crate(cargo_dir)
|
|
||||||
.with_language(cbindgen::Language::C)
|
|
||||||
.generate()
|
|
||||||
.expect("Unable to generate bindings")
|
|
||||||
.write_to_file(&out);
|
|
||||||
|
|
||||||
println!("cargo:rerun-if-changed={}", out.display());
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
/* Hello World Example
|
|
||||||
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is an empty source file to force the build of a CMake library that
|
|
||||||
can participate in the CMake dependency graph. This placeholder library
|
|
||||||
will depend on the actual library generated by external Rust build.
|
|
||||||
*/
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
[toolchain]
|
|
||||||
channel = "esp"
|
|
||||||
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
|
||||||
#![cfg_attr(not(version("1.59")), feature(asm))]
|
|
||||||
#![cfg_attr(
|
|
||||||
all(version("1.58"), target_arch = "xtensa"),
|
|
||||||
feature(asm_experimental_arch)
|
|
||||||
)]
|
|
||||||
#![feature(cfg_version)]
|
|
||||||
use core::arch::asm;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
use core::panic::PanicInfo;
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn add_in_rust(x: i32, y: i32) -> i32 {
|
|
||||||
x + y
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn add_in_rust_inline_asm(mut x: i32, y: i32) -> i32 {
|
|
||||||
unsafe {
|
|
||||||
// more detail available: https://doc.rust-lang.org/beta/unstable-book/library-features/asm.html
|
|
||||||
asm!("add {0}, {0}, {1}", inout(reg) x, in(reg) y);
|
|
||||||
}
|
|
||||||
x
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(_info: &PanicInfo) -> ! {
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
idf_component_register(SRCS "main.c"
|
idf_component_register(SRCS "main.cpp"
|
||||||
INCLUDE_DIRS "")
|
INCLUDE_DIRS "")
|
||||||
|
|
|
||||||
64
main/main.c
64
main/main.c
|
|
@ -1,64 +0,0 @@
|
||||||
/* Hello World Example
|
|
||||||
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_system.h"
|
|
||||||
#include "esp_flash.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_idf_version.h"
|
|
||||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
|
||||||
#include "esp_chip_info.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "RustApi.h"
|
|
||||||
|
|
||||||
void app_main(void)
|
|
||||||
{
|
|
||||||
uint32_t flash_size;
|
|
||||||
|
|
||||||
printf("Hello world!\n");
|
|
||||||
|
|
||||||
/* Print chip information */
|
|
||||||
esp_chip_info_t chip_info;
|
|
||||||
esp_chip_info(&chip_info);
|
|
||||||
printf("This is %s chip with %d CPU cores, WiFi%s%s, ",
|
|
||||||
CONFIG_IDF_TARGET,
|
|
||||||
chip_info.cores,
|
|
||||||
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
|
|
||||||
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
|
|
||||||
|
|
||||||
printf("silicon revision %d, ", chip_info.revision);
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK( esp_flash_get_size(NULL, &flash_size) );
|
|
||||||
printf("%"PRIu32"MB %s flash\n", flash_size / (1024 * 1024),
|
|
||||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
|
|
||||||
|
|
||||||
printf("Free heap: %"PRIu32"\n", esp_get_free_heap_size());
|
|
||||||
|
|
||||||
int x = 2;
|
|
||||||
int y = 3;
|
|
||||||
int sum = add_in_rust(x, y);
|
|
||||||
printf("Rust calculated %d + %d = %d\n\n", x, y, sum);
|
|
||||||
|
|
||||||
x = 9;
|
|
||||||
y = 10;
|
|
||||||
sum = add_in_rust_inline_asm(x, y);
|
|
||||||
printf("Rust calculated (using asm!) %d + %d = %d\n\n", x, y, sum);
|
|
||||||
|
|
||||||
for (int i = 10; i >= 0; i--) {
|
|
||||||
printf("Restarting in %d seconds...\n", i);
|
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
printf("Restarting now.\n");
|
|
||||||
fflush(stdout);
|
|
||||||
esp_restart();
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
/* Hello World Example
|
||||||
|
|
||||||
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, this
|
||||||
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*/
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_flash.h"
|
||||||
|
#include "esp_idf_version.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||||
|
#include "esp_chip_info.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "drone_controller.h"
|
||||||
|
|
||||||
|
extern "C" void app_main(void) {
|
||||||
|
uint32_t flash_size;
|
||||||
|
|
||||||
|
printf("Hello world!\n");
|
||||||
|
|
||||||
|
/* Print chip information */
|
||||||
|
esp_chip_info_t chip_info;
|
||||||
|
esp_chip_info(&chip_info);
|
||||||
|
printf("This is %s chip with %d CPU cores, WiFi%s%s, ", CONFIG_IDF_TARGET,
|
||||||
|
chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
|
||||||
|
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
|
||||||
|
|
||||||
|
printf("silicon revision %d, ", chip_info.revision);
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_flash_get_size(NULL, &flash_size));
|
||||||
|
printf("%" PRIu32 "MB %s flash\n", flash_size / (1024 * 1024),
|
||||||
|
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded"
|
||||||
|
: "external");
|
||||||
|
|
||||||
|
printf("Free heap: %" PRIu32 "\n", esp_get_free_heap_size());
|
||||||
|
|
||||||
|
for (int i = 10; i >= 0; i--) {
|
||||||
|
printf("Restarting in %d seconds...\n", i);
|
||||||
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
printf("Restarting now.\n");
|
||||||
|
fflush(stdout);
|
||||||
|
esp_restart();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue