diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..f663373 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,31 @@ +name: CI + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + timeout-minutes: 5 + + strategy: + matrix: + device: ['longan-nano', 'longan-nano-lite'] + + steps: + - uses: actions/checkout@v3 + + - name: Install RISC-V build dependencies + run: sudo apt-get install build-essential binutils-riscv64-unknown-elf gcc-riscv64-unknown-elf + + - name: Build the FiveForths firmware binary for ${{matrix.device}} + run: make ${{matrix.device}} + + - name: Obtain SHA256 hash of the firmware ${{matrix.device}}.bin + run: sha256sum fiveforths.bin > fiveforths.bin.sha256 + + - uses: actions/upload-artifact@v3 + with: + name: fiveforths-firmware-${{matrix.device}} + path: fiveforths.bin* diff --git a/Makefile b/Makefile index e47adae..fcaa335 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,6 @@ PROGNAME = fiveforths CFLAGS := -g -ARCH ?= rv32imac # rv32imac for Longan Nano -EMU ?= elf32lriscv CROSS ?= /usr/bin/riscv64-unknown-elf- AS := $(CROSS)as LD := $(CROSS)ld @@ -13,15 +11,21 @@ OBJCOPY := $(CROSS)objcopy OBJDUMP := $(CROSS)objdump READELF := $(CROSS)readelf +# MCU and board specific variables +ARCH ?= rv32imac +EMU ?= elf32lriscv +MCU ?= gd32vf103 +BOARD ?= longan-nano-lite + .PHONY: clean build: $(PROGNAME).o $(PROGNAME).elf $(PROGNAME).bin $(PROGNAME).hex $(PROGNAME).dump %.o: %.s - $(AS) $(CFLAGS) -march=$(ARCH) -I src -o $@ $< + $(AS) $(CFLAGS) -march=$(ARCH) -I src/boards/$(BOARD) -I src/mcus/$(MCU) -I src -o $@ $< %.elf: %.o - $(LD) -m $(EMU) -T $(PROGNAME).ld -o $@ $< + $(LD) -m $(EMU) -T src/boards/$(BOARD)/linker.ld -o $@ $< %.bin: %.elf $(OBJCOPY) -O binary $< $@ @@ -44,5 +48,11 @@ openocd: debug: /opt/riscv/bin/riscv64-unknown-elf-gdb -command=debug.gdb -q fiveforths.elf +longan-nano: + $(MAKE) build BOARD=longan-nano + +longan-nano-lite: + $(MAKE) build BOARD=longan-nano-lite + clean: rm -v *.bin *.elf *.o *.hex *.dump diff --git a/README.md b/README.md index 9d5a878..613990f 100644 --- a/README.md +++ b/README.md @@ -30,12 +30,14 @@ Development progress has been logged regularly in the [devlogs](https://aw.githu # Getting started +It is possible to download a firmware binary or build the firmware manually. + ## Download it Download one of the firmware binaries from the [releases page](https://github.com/aw/fiveforths/releases). -* [fiveforths-longan-nano-lite.bin](https://github.com/aw/fiveforths/releases/download/v0.1/fiveforths-longan-nano-lite.bin) (64K Flash, 20K RAM) -* [fiveforths-longan-nano.bin](https://github.com/aw/fiveforths/releases/download/v0.1/fiveforths-longan-nano.bin) (128K Flash, 32K RAM) +* [fiveforths-longan-nano-lite.bin](https://github.com/aw/fiveforths/releases/download/v0.2/fiveforths-longan-nano-lite.bin) (64K Flash, 20K RAM) +* [fiveforths-longan-nano.bin](https://github.com/aw/fiveforths/releases/download/v0.2/fiveforths-longan-nano.bin) (128K Flash, 32K RAM) ## Build it @@ -65,7 +67,7 @@ $ make /usr/bin/riscv64-unknown-elf-objdump -D -S fiveforths.elf > fiveforths.dump ``` -The firmware file is called `fiveforths.bin` and is **under 2 KBytes** as of _January 08, 2023_. +The firmware file is called `fiveforths.bin` and is **under 2 KBytes** as of _release v0.1_ since _January 08, 2023_. # Flashing the firmware @@ -121,7 +123,7 @@ The source files are: # TODO - [ ] Finish writing this README -- [ ] Fix remaining bugs (carriage return issue) +- [x] Fix remaining bugs (carriage return issue) - [ ] Implement bounds checks for stacks and dictionary - [ ] Code cleanup and optimizations - [ ] Add example Forth code to turn it into a "real" Forth (ex: `[`, `]`, `branch`, etc) @@ -132,7 +134,14 @@ Please create a pull-request or [open an issue](https://github.com/aw/picolisp-k # Changelog -* 2023-01-09 - First release +## 0.2 (2023-01-10) + + * Fix issue #9 - Handling of carriage return + * Fix issue #11 - Ignore non-printable characters + * Re-organize code to support different boards and MCUs + * Add GitHub action to automatically build and publish the firmware binaries + +## 0.1 2023-01-09 - First release # Other Forths diff --git a/fiveforths.s b/fiveforths.s index 2900e90..e0d4913 100644 --- a/fiveforths.s +++ b/fiveforths.s @@ -19,13 +19,16 @@ Copyright (c) 2021 Alexander Williams, On-Prem # s1 = IP = instruction pointer # s2 = RSP = return stack pointer +# include board-specific functions and constants from src/boards// +.include "board.s" + +# include MCU-specific functions and constants from src/mcus// +.include "mcu.s" + +# include source files from src/ .include "01-variables-constants.s" .include "02-macros.s" .include "03-interrupts.s" - -# include board-specific functions -.include "gd32vf103.s" - .include "04-io-helpers.s" .include "05-internal-functions.s" .include "06-initialization.s" diff --git a/src/01-variables-constants.s b/src/01-variables-constants.s index 0b2a25d..b2bc6ee 100644 --- a/src/01-variables-constants.s +++ b/src/01-variables-constants.s @@ -8,12 +8,6 @@ # Memory map ## -# adjust these values for specific targets -.equ CELL, 4 # 32-bits cell size -.equ RAM_BASE, 0x20000000 # base address of RAM -.equ RAM_SIZE, 1024 * 20 # 20 KiB -.equ STACK_SIZE, 256 # 256 Bytes - # DSP, RSP, TIB stacks grow downward from the top of memory .equ DSP_TOP, RAM_BASE + RAM_SIZE # address of top of data stack .equ RSP_TOP, DSP_TOP - STACK_SIZE # address of top of return stack @@ -36,7 +30,7 @@ ## .equ CHAR_NEWLINE, '\n' # newline character 0x0A -.equ CHAR_CARRIAGE, '\r' # carriage return character 0x13 +.equ CHAR_CARRIAGE, '\r' # carriage return character 0x0D .equ CHAR_SPACE, ' ' # space character 0x20 .equ CHAR_BACKSPACE, '\b' # backspace character 0x08 .equ CHAR_COMMENT, '\\' # backslash character 0x5C diff --git a/src/09-interpreter.s b/src/09-interpreter.s index cced749..3b3d940 100644 --- a/src/09-interpreter.s +++ b/src/09-interpreter.s @@ -14,6 +14,13 @@ interpreter: call uart_get # read a character from UART li t4, CHAR_NEWLINE # load newline into temporary beq a0, t4, skip_send # don't send the character if it's a newline + + # ignore specific characters + mv t4, zero # load 0x00 zero into temporary + beq a0, t4, interpreter # ignore the character if it matches + li t4, CHAR_CARRIAGE # load 0x0D carriage return into temporary + beq a0, t4, interpreter # ignore the character if it matches + call uart_put # send the character to UART skip_send: @@ -27,11 +34,6 @@ skip_send: li t0, CHAR_BACKSPACE # load backspace into temporary beq a0, t0, process_backspace # process the backspace if it matches - li t0, CHAR_CARRIAGE # load carriage return into temporary - beq a0, t0, process_carriage # process the carriage return if it matches - - # TODO: check if character is printable - interpreter_tib: # add the character to the TIB li t4, TIB_TOP # load TIB_TOP memory address @@ -64,10 +66,6 @@ process_backspace: j interpreter # return to the interpreter after erasing the character -process_carriage: - li a0, CHAR_NEWLINE # convert a carriage return to a newline - j interpreter_tib # jump to add the character to the TIB - .balign CELL replace_newline: li a0, CHAR_SPACE # convert newline to a space diff --git a/src/boards/longan-nano-lite/board.s b/src/boards/longan-nano-lite/board.s new file mode 100644 index 0000000..28d5fb1 --- /dev/null +++ b/src/boards/longan-nano-lite/board.s @@ -0,0 +1,5 @@ +## +# Longan Nano Lite +## + +.equ RAM_SIZE, 1024 * 20 # 20 KiB diff --git a/fiveforths.ld b/src/boards/longan-nano-lite/linker.ld similarity index 96% rename from fiveforths.ld rename to src/boards/longan-nano-lite/linker.ld index 1d3941f..68fb1a2 100644 --- a/fiveforths.ld +++ b/src/boards/longan-nano-lite/linker.ld @@ -1,3 +1,4 @@ +/* GD32VF103C8 */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64k diff --git a/src/boards/longan-nano/board.s b/src/boards/longan-nano/board.s new file mode 100644 index 0000000..c66d727 --- /dev/null +++ b/src/boards/longan-nano/board.s @@ -0,0 +1,5 @@ +## +# Longan Nano +## + +.equ RAM_SIZE, 1024 * 32 # 32 KiB diff --git a/src/boards/longan-nano/linker.ld b/src/boards/longan-nano/linker.ld new file mode 100644 index 0000000..24a9486 --- /dev/null +++ b/src/boards/longan-nano/linker.ld @@ -0,0 +1,22 @@ +/* GD32VF103CB */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128k + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32k +} + +/* The entry point is the reset handler */ +ENTRY(_start); + +SECTIONS { + __stacktop = ORIGIN(RAM) + LENGTH(RAM); + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + } >FLASH + +} diff --git a/gd32vf103.s b/src/mcus/gd32vf103/mcu.s similarity index 94% rename from gd32vf103.s rename to src/mcus/gd32vf103/mcu.s index c53c828..100048f 100644 --- a/gd32vf103.s +++ b/src/mcus/gd32vf103/mcu.s @@ -2,6 +2,11 @@ # GD32VF103 ## +.equ CELL, 4 # 32-bits cell size +.equ RAM_BASE, 0x20000000 # base address of RAM +.equ STACK_SIZE, 256 # 256 Bytes + +# UART .equ USART0_BASE_ADDRESS, 0x40013800 .equ UART_RX_STATUS, 0x00 # USART status register offset (USART_STAT) .equ UART_RX_DATA, 0x04 # data register offset (USART_DATA)