diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4a67053 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/mruby/mruby"] + path = lib/mruby/mruby + url = https://github.com/mruby/mruby.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bf177c..af242b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/Core/Src/libc-hooks.c b/Core/Src/libc-hooks.c new file mode 100644 index 0000000..1538b05 --- /dev/null +++ b/Core/Src/libc-hooks.c @@ -0,0 +1,67 @@ +#include +#include + +#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; +} \ No newline at end of file diff --git a/Core/Src/main.c b/Core/Src/main.c index 0e8d420..2948810 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -22,6 +22,11 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ +#include + +#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 */ diff --git a/lib/mruby/build_config.rb b/lib/mruby/build_config.rb new file mode 100644 index 0000000..0295fd4 --- /dev/null +++ b/lib/mruby/build_config.rb @@ -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 + \ No newline at end of file diff --git a/lib/mruby/build_mruby.sh b/lib/mruby/build_mruby.sh new file mode 100644 index 0000000..230abdf --- /dev/null +++ b/lib/mruby/build_mruby.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +cd mruby + +rake MRUBY_CONFIG=../build_config.rb \ No newline at end of file diff --git a/lib/mruby/gems/sleep/mrbgem.rake b/lib/mruby/gems/sleep/mrbgem.rake new file mode 100644 index 0000000..49afd48 --- /dev/null +++ b/lib/mruby/gems/sleep/mrbgem.rake @@ -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 \ No newline at end of file diff --git a/lib/mruby/gems/sleep/src/sleep.c b/lib/mruby/gems/sleep/src/sleep.c new file mode 100644 index 0000000..312d320 --- /dev/null +++ b/lib/mruby/gems/sleep/src/sleep.c @@ -0,0 +1,32 @@ +#include +#include + +#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 */ +} diff --git a/lib/mruby/mruby b/lib/mruby/mruby new file mode 160000 index 0000000..69b1667 --- /dev/null +++ b/lib/mruby/mruby @@ -0,0 +1 @@ +Subproject commit 69b1667b5ba4d245c76d1cb99f2c813eae78b3e9