A simple idea of to include the build date and time as information turned out to be a a struggle to get the toolchain and project files correct.
We needed to change the extension from ".s" to capital ".S" which goes through the C++ preprocess. Small s is pure assembler.
We now take the date-time of the build.
# -----------------------------------------------------------------------
# Build Date and Time
# -----------------------------------------------------------------------
# Get the current build date and time
BUILD_DATE := $(shell TZ=$(shell date +"%Z") date +"%Y-%m-%d_%H:%M:%S")
We add these to the flags.
# -----------------------------------------------------------------------
# Compiler and Linker Flags
# -----------------------------------------------------------------------
ASFLAGS = -march=rv32g -mabi=ilp32 -static -mcmodel=medany \
-fvisibility=hidden -nostdlib -nostartfiles -I$(INCLUDE_DIR)
ASFLAGS += -DDEBUG_LEVEL=$(DEBUG_LEVEL) -DTRACE_LEVEL=$(TRACE_LEVEL) -DLOG_LEVEL=$(LOG_LEVEL)
ASFLAGS += -DBUILD_DATE=\"$(BUILD_DATE)\"
ASFLAGS += -I$(INCLUDE_DIR)
I have an rodata.S file that will be C++ preprocessed from src to build, and later we link that generated build file into the compiled end result and ignore the one found in the src
# -----------------------------------------------------------------------
# Rule to Generate Build-Specific rodata.S
# -----------------------------------------------------------------------
$(BUILD_DIR)/data/rodata.S: $(DATA_DIR)/rodata.S
@mkdir -p $(dir $@) # Ensure the output directory exists
@echo "Generating rodata.S with build date: $(BUILD_DATE)"
sed 's/BUILD_DATE_PLACEHOLDER/$(BUILD_DATE)/' $< > $@
Compilation should now take ".s" and ".S" files
# -----------------------------------------------------------------------
# Source Files
# -----------------------------------------------------------------------
GLOBAL_CONSTANTS_FILE = $(INCLUDE_DIR)/global_constants.S
SRC = $(GLOBAL_CONSTANTS_FILE) \
$(INCLUDE_DIR)/global_constants.S \
$(DATA_DIR)/data.S \
$(BUILD_DIR)/data/rodata.S \
$(DATA_DIR)/bss.S \
$(wildcard $(UNIT_TESTS_DIR)/strings-module/*.[sS]) \
$(wildcard $(MODULES_DIR)/debug-module/*.[sS]) \
$(wildcard $(MODULES_DIR)/timing-module/*.[sS]) \
$(wildcard $(MODULES_DIR)/strings-module/*.[sS]) \
$(wildcard $(MODULES_DIR)/info-module/*.[sS]) \
$(BOOT_DIR)/boot.S \
$(SRC_DIR)/main.S
Output now send to the UART
ATE0--> Send Flag error: #255 #255 #255 #255 AT+BLEINIT=0--> Send Flag error: #255 #255 #255 #255 AT+CWMODE=0--> Send Flag error: #255 #255 #255 #255
[LOG] SparkFun Red-V bare metal v1.0.
[LOG] Build Date: 2024-11-01_16:49:21
[LOG]
The rodata.S
Note the BUILD_DATE_PLACEHOLDER inside the string as defined in the make file
# rodata.S
.align 2
.section .rodata
.globl VERSION_INFO
VERSION_INFO:
.asciz "SparkFun Red-V bare metal v1.0."
.globl BUILD_DATE_STR
BUILD_DATE_STR:
.asciz "Build Date: BUILD_DATE_PLACEHOLDER"
Complete update make file
# Makefile for building assembly code for the SparkFun Red-V development board # ----------------------------------------------------------------------- # Toolchain Configuration # ----------------------------------------------------------------------- TOOLCHAIN_PREFIX = riscv64-unknown-elf- CC = $(TOOLCHAIN_PREFIX)gcc OBJCOPY = $(TOOLCHAIN_PREFIX)objcopy # ----------------------------------------------------------------------- # Default Flag Values (can be overridden from the command line) # ----------------------------------------------------------------------- DEBUG_LEVEL ?= 2 TRACE_LEVEL ?= 1 LOG_LEVEL ?= 5 # ----------------------------------------------------------------------- # Build Date and Time # ----------------------------------------------------------------------- # Get the current build date and time BUILD_DATE := $(shell TZ=$(shell date +"%Z") date +"%Y-%m-%d_%H:%M:%S") # ----------------------------------------------------------------------- # Compiler and Linker Flags # ----------------------------------------------------------------------- ASFLAGS = -march=rv32g -mabi=ilp32 -static -mcmodel=medany \ -fvisibility=hidden -nostdlib -nostartfiles -I$(INCLUDE_DIR) ASFLAGS += -DDEBUG_LEVEL=$(DEBUG_LEVEL) -DTRACE_LEVEL=$(TRACE_LEVEL) -DLOG_LEVEL=$(LOG_LEVEL) ASFLAGS += -DBUILD_DATE=\"$(BUILD_DATE)\" ASFLAGS += -I$(INCLUDE_DIR) # Remove dependency generation flags # ASFLAGS += -MD -MP LDFLAGS = -T sparkfun-red-v.ld # ----------------------------------------------------------------------- # Directories # ----------------------------------------------------------------------- SRC_DIR = src BOOT_DIR = $(SRC_DIR)/boot INCLUDE_DIR = $(SRC_DIR)/include DATA_DIR = $(SRC_DIR)/data UNIT_TESTS_DIR = $(SRC_DIR)/unit-tests MODULES_DIR = $(SRC_DIR)/modules BUILD_DIR = build # ----------------------------------------------------------------------- # Source Files # ----------------------------------------------------------------------- GLOBAL_CONSTANTS_FILE = $(INCLUDE_DIR)/global_constants.S SRC = $(GLOBAL_CONSTANTS_FILE) \ $(INCLUDE_DIR)/global_constants.S \ $(DATA_DIR)/data.S \ $(BUILD_DIR)/data/rodata.S \ $(DATA_DIR)/bss.S \ $(wildcard $(UNIT_TESTS_DIR)/strings-module/*.[sS]) \ $(wildcard $(MODULES_DIR)/debug-module/*.[sS]) \ $(wildcard $(MODULES_DIR)/timing-module/*.[sS]) \ $(wildcard $(MODULES_DIR)/strings-module/*.[sS]) \ $(wildcard $(MODULES_DIR)/info-module/*.[sS]) \ $(BOOT_DIR)/boot.S \ $(SRC_DIR)/main.S # ----------------------------------------------------------------------- # Object Files # ----------------------------------------------------------------------- OBJ = $(patsubst $(SRC_DIR)/%.[sS],$(BUILD_DIR)/%.o,$(SRC)) # ----------------------------------------------------------------------- # Targets # ----------------------------------------------------------------------- ELF = $(BUILD_DIR)/main.elf HEX = $(BUILD_DIR)/main.hex .PHONY: all clean rebuild # ----------------------------------------------------------------------- # Default Target # ----------------------------------------------------------------------- all: $(BUILD_DIR) $(HEX) # ----------------------------------------------------------------------- # Create Build Directory # ----------------------------------------------------------------------- $(BUILD_DIR): @mkdir -p $(BUILD_DIR) # ----------------------------------------------------------------------- # Rule to Build HEX File from ELF # ----------------------------------------------------------------------- $(HEX): $(ELF) $(OBJCOPY) -O ihex $< $@ # ----------------------------------------------------------------------- # Rule to Build ELF from Object Files # ----------------------------------------------------------------------- $(ELF): $(OBJ) $(CC) $(ASFLAGS) $(LDFLAGS) $^ -o $@ # ----------------------------------------------------------------------- # Rule to Compile .s and .S Files to .o Files # ----------------------------------------------------------------------- $(BUILD_DIR)/%.o: $(SRC_DIR)/%.[sS] @mkdir -p $(dir $@) $(CC) $(ASFLAGS) -c $< -o $@ # ----------------------------------------------------------------------- # Rule to Generate Build-Specific rodata.S # ----------------------------------------------------------------------- $(BUILD_DIR)/data/rodata.S: $(DATA_DIR)/rodata.S @mkdir -p $(dir $@) # Ensure the output directory exists @echo "Generating rodata.S with build date: $(BUILD_DATE)" sed 's/BUILD_DATE_PLACEHOLDER/$(BUILD_DATE)/' $< > $@ # Add similar dependency rules for other object files if necessary # ----------------------------------------------------------------------- # Build Time File to Force Rebuild of Files that Depend on BUILD_DATE # ----------------------------------------------------------------------- BUILD_TIME_FILE := $(BUILD_DIR)/build_time .PHONY: $(BUILD_TIME_FILE) $(BUILD_TIME_FILE): @echo $(BUILD_DATE) > $(BUILD_TIME_FILE) # ----------------------------------------------------------------------- # Clean Up Build Artifacts # ----------------------------------------------------------------------- clean: rm -rf $(BUILD_DIR) # ----------------------------------------------------------------------- # Rebuild Target # ----------------------------------------------------------------------- rebuild: clean all
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
Thank you for your feedback.
The idea is that I want to avoid any usage of C, I want to write everything in as much as assembler as possible. Not constrained by C language.
What I forgot in the blog post is how I would use it:
.globl BUILD_DATE_STR
BUILD_DATE_STR: .asciz "Build Date: BUILD_DATE_PLACEHOLDER"
I tried your suggestion __DATE__ but the compiler complaints with an error.
---
build/data/rodata.S: Assembler messages:
---build/data/rodata.S:6: Error: junk at end of line, first unrecognized character is `_'
make: *** [Makefile:100: build/main.elf] Error 1
Are you sure? yes | no
But the point is that .S files go through cpp and those macros are predefined in cpp.
Are you sure? yes | no
I can't seem to compile it, but in my project I have no cpp reference, no standard library whatsoever. Just bare metal.
Are you sure? yes | no
cpp stands for C PreProcessor which handles #defines, #includes and so forth, and is part of the gcc toolchain and is automatically invoked by gcc. But it's not limited to preprocessing C and can also preprocess other languages. You'd have to look at the cpp documentation to see how to invoke it (safely) on assembler. On my system man cpp works.
Are you sure? yes | no
Couldn't you use the predefined macros __DATE__ and __TIME__ in your rodata source?
Are you sure? yes | no