Working MRuby port.

This commit is contained in:
imi415 2022-01-10 23:48:51 +08:00
parent 0fb8ffa103
commit a7d13aa30f
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
9 changed files with 249 additions and 0 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "lib/mruby/mruby"]
path = lib/mruby/mruby
url = https://github.com/mruby/mruby.git

View File

@ -16,6 +16,7 @@ set(TARGET_LDSCRIPT_RAM "${CMAKE_SOURCE_DIR}/STM32H750VBTx_RAM.ld")
# Copy them from Makefile
set(TARGET_C_SOURCES
"Core/Src/libc-hooks.c"
"Core/Src/main.c"
"Core/Src/stm32h7xx_it.c"
"Core/Src/stm32h7xx_hal_msp.c"
@ -76,14 +77,17 @@ set(TARGET_C_INCLUDES
"Drivers/STM32H7xx_HAL_Driver/Inc/Legacy"
"Drivers/CMSIS/Device/ST/STM32H7xx/Include"
"Drivers/CMSIS/Include"
"lib/mruby/mruby/include"
)
# Shared libraries linked with application
set(TARGET_LIBS
"mruby"
)
# Shared library and linker script search paths
set(TARGET_LIB_DIRECTORIES
"lib/mruby/mruby/build/STM32H750/lib"
)
# Device specific settings, goes to CFLAGS and LDFLAGS

67
Core/Src/libc-hooks.c Normal file
View File

@ -0,0 +1,67 @@
#include <stdio.h>
#include <sys/stat.h>
#include "stm32h7xx_hal.h"
extern UART_HandleTypeDef huart1;
/* Place heap inside DTCMRAM. */
#define HEAP_BASE 0x20000000
#define HEAP_SIZE 0x00020000
size_t s_heap_sz = 0;
int _getpid(void) {
return 0;
}
int _kill(int i, int j) {
return 0;
}
int _read(int fd, char *buf, int nbytes) {
return 0;
}
int _write(int fd, const void *buf, int nbytes) {
HAL_StatusTypeDef res;
res = HAL_UART_Transmit(&huart1, (uint8_t *)buf, nbytes, 1000);
if(res != HAL_OK) {
return 0;
}
return nbytes;
}
int _close(int file) {
return -1;
}
int _isatty(int file) {
return file <= 2;
}
int _fstat(int file, struct stat *st) {
st->st_mode = S_IFCHR;
return 0;
}
int _lseek(int file, int ptr, int dir){
return 0;
}
void *_sbrk(intptr_t count) {
void *ret, *ptr;
ptr = ((char *)HEAP_BASE) + s_heap_sz;
if(s_heap_sz + count < HEAP_SIZE) {
s_heap_sz += count;
ret = ptr;
}
else {
ret = (void *)-1;
}
return ret;
}

View File

@ -22,6 +22,11 @@
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <malloc.h>
#include "mruby.h"
#include "mruby/compile.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@ -57,6 +62,11 @@ static void MX_USART1_UART_Init(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static void report_heap(void) {
struct mallinfo mi = mallinfo();
printf("\r\nHeap usage: %d bytes.\r\n", mi.uordblks);
}
/* USER CODE END 0 */
/**
@ -90,6 +100,33 @@ int main(void)
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
char *script_str =
"puts \"mruby v#{RUBY_VERSION} on STM32!\\r\\n\"\n"
"i = 0\n"
"loop do\n"
" puts \"Hello world ##{i}\\r\\n\"\n"
" i += 1\n"
" Sleep.sleep_ms(1000)\n"
"end\n";
printf("\r\nInitializing MRB core.\r\n");
report_heap();
mrb_state *mrb = mrb_open();
printf("MRB: %p\r\n", mrb);
mrb_load_string(mrb, script_str);
report_heap();
mrb_close(mrb);
printf("Closed MRB core.\r\n");
report_heap();
/* USER CODE END 2 */
/* Infinite loop */

64
lib/mruby/build_config.rb Normal file
View File

@ -0,0 +1,64 @@
MRuby::CrossBuild.new("STM32H750") do |conf|
toolchain :gcc
# Linux
BIN_PATH = "/usr/bin"
conf.cc do |cc|
cc.command = "#{BIN_PATH}/arm-none-eabi-gcc"
cc.flags = "-Wall -g -O2 -flto -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16"
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
#configuration for low memory environment
#cc.defines << %w(MRB_USE_FLOAT32)
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
cc.defines << %w(MRB_GC_STRESS)
#cc.defines << %w(MRB_NO_STDIO) #if you don't need stdio.
#cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
end
conf.cxx do |cxx|
cxx.command = conf.cc.command.dup
cxx.include_paths = conf.cc.include_paths.dup
cxx.flags = conf.cc.flags.dup
cxx.defines = conf.cc.defines.dup
cxx.compile_options = conf.cc.compile_options.dup
end
conf.linker do |linker|
linker.command="#{BIN_PATH}/arm-none-eabi-gcc"
end
conf.archiver do |archiver|
archiver.command = "#{BIN_PATH}/arm-none-eabi-ar"
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
end
#no executables
conf.bins = []
#do not build executable test
conf.build_mrbtest_lib_only
#disable C++ exception
conf.disable_cxx_exception
#gems from core
conf.gem :core => "mruby-compiler"
conf.gem :core => "mruby-enum-ext"
conf.gem :core => "mruby-math"
conf.gem :core => "mruby-numeric-ext"
conf.gem :core => "mruby-print"
conf.gem :core => "mruby-sprintf"
#light-weight regular expression
#conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master"
#Arduino API
#conf.gem :github =>"kyab/mruby-arduino", :branch => "master"
conf.gem 'gems/sleep'
end

5
lib/mruby/build_mruby.sh Normal file
View File

@ -0,0 +1,5 @@
#!/bin/bash
cd mruby
rake MRUBY_CONFIG=../build_config.rb

View File

@ -0,0 +1,36 @@
PROJ_ROOT="../../.."
MRuby::Gem::Specification.new('sleep') do |spec|
spec.license = 'MIT'
spec.author = 'imi415'
spec.cc.include_paths << "#{PROJ_ROOT}/Drivers/STM32H7xx_HAL_Driver/Inc"
spec.cc.include_paths << "#{PROJ_ROOT}/Core/Inc"
spec.cc.include_paths << "#{PROJ_ROOT}/Drivers/STM32H7xx_HAL_Driver/Inc/Legacy"
spec.cc.include_paths << "#{PROJ_ROOT}/Drivers/CMSIS/Device/ST/STM32H7xx/Include"
spec.cc.include_paths << "#{PROJ_ROOT}/Drivers/CMSIS/Include"
spec.cc.defines << "STM32H750xx"
spec.cc.defines << "USE_HAL_DRIVER"
# Add compile flags
# spec.cc.flags << '-g'
# Add cflags to all
# spec.mruby.cc.flags << '-g'
# Add libraries
# spec.linker.libraries << 'external_lib'
# Default build files
# spec.rbfiles = Dir.glob("#{dir}/mrblib/*.rb")
# spec.objs = Dir.glob("#{dir}/src/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
# spec.test_rbfiles = Dir.glob("#{dir}/test/*.rb")
# spec.test_objs = Dir.glob("#{dir}/test/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
# spec.test_preload = 'test/assert.rb'
# Values accessible as TEST_ARGS inside test scripts
# spec.test_args = {'tmp_dir' => Dir::tmpdir}
end

View File

@ -0,0 +1,32 @@
#include <mruby.h>
#include <mruby/string.h>
#include "stm32h7xx_hal.h"
static mrb_value sleep_ms_c_method(mrb_state* mrb, mrb_value self) {
mrb_value* argv;
mrb_int argc;
mrb_get_args(mrb, "*", &argv, &argc);
int iargc = (int)argc;
if (iargc == 0 || iargc >= 2) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
}
if (mrb_fixnum_p(argv[0]) && mrb_fixnum(argv[0]) >= 0) {
HAL_Delay(mrb_fixnum(argv[0]));
} else {
mrb_raise(mrb, E_ARGUMENT_ERROR, "time interval must be positive integer");
}
return self;
}
void mrb_sleep_gem_init(mrb_state* mrb) {
struct RClass* class_cextension = mrb_define_module(mrb, "Sleep");
mrb_define_class_method(mrb, class_cextension, "sleep_ms", sleep_ms_c_method, MRB_ARGS_REQ(1));
}
void mrb_sleep_gem_final(mrb_state* mrb) { /* finalizer */
}

1
lib/mruby/mruby Submodule

@ -0,0 +1 @@
Subproject commit 69b1667b5ba4d245c76d1cb99f2c813eae78b3e9