initial commit
This commit is contained in:
commit
823f030974
8 changed files with 461 additions and 0 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use flake
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
.cache/
|
||||||
|
.direnv/
|
||||||
|
build/
|
||||||
|
compile_commands.json
|
||||||
|
result
|
||||||
67
Makefile
Normal file
67
Makefile
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
PREFIX ?= arm-none-eabi-
|
||||||
|
CC = $(PREFIX)gcc
|
||||||
|
OBJCOPY = $(PREFIX)objcopy
|
||||||
|
SIZE = $(PREFIX)size
|
||||||
|
|
||||||
|
PNAME := bincnt
|
||||||
|
BUILD := build
|
||||||
|
|
||||||
|
# libopencm3 is provided by the Nix shell
|
||||||
|
OPENCM3_DIR ?= ""
|
||||||
|
|
||||||
|
SRCS := src/main.c
|
||||||
|
OBJS := $(addprefix $(BUILD)/, $(SRCS:.c=.o))
|
||||||
|
|
||||||
|
# STM32G4
|
||||||
|
CPU_FLAGS := -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||||
|
|
||||||
|
CFLAGS := $(CPU_FLAGS) \
|
||||||
|
-DSTM32G4 \
|
||||||
|
-Os -Wall -Wextra \
|
||||||
|
-ffunction-sections -fdata-sections \
|
||||||
|
-I$(OPENCM3_DIR)/include
|
||||||
|
|
||||||
|
LDFLAGS := $(CPU_FLAGS) \
|
||||||
|
-nostartfiles \
|
||||||
|
-Wl,--gc-sections \
|
||||||
|
-L$(OPENCM3_DIR)/lib \
|
||||||
|
-lopencm3_stm32g4
|
||||||
|
|
||||||
|
ELF := $(BUILD)/$(PNAME).elf
|
||||||
|
BIN := $(BUILD)/$(PNAME).bin
|
||||||
|
HEX := $(BUILD)/$(PNAME).hex
|
||||||
|
|
||||||
|
.PHONY: all clean flash size
|
||||||
|
|
||||||
|
all: $(BIN) $(HEX) size
|
||||||
|
|
||||||
|
$(BUILD)/%.o: %.c
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
LDSCRIPT := $(BUILD)/stm32g474xe.ld
|
||||||
|
|
||||||
|
$(LDSCRIPT):
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(CC) -I$(OPENCM3_DIR)/include $(shell python3 $(OPENCM3_DIR)/scripts/genlink.py $(OPENCM3_DIR)/ld/devices.data stm32g474xe DEFS) -P -E $(OPENCM3_DIR)/ld/linker.ld.S -o $@
|
||||||
|
|
||||||
|
$(ELF): $(OBJS) $(LDSCRIPT)
|
||||||
|
$(CC) $(OBJS) $(LDFLAGS) -T$(LDSCRIPT) -o $@
|
||||||
|
|
||||||
|
$(BIN): $(ELF)
|
||||||
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
|
$(HEX): $(ELF)
|
||||||
|
$(OBJCOPY) -O ihex $< $@
|
||||||
|
|
||||||
|
size: $(ELF)
|
||||||
|
$(SIZE) $<
|
||||||
|
|
||||||
|
flash: $(BIN)
|
||||||
|
openocd \
|
||||||
|
-f interface/stlink.cfg \
|
||||||
|
-f target/stm32g4x.cfg \
|
||||||
|
-c "program $(BIN) verify reset exit 0x08000000"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILD)
|
||||||
1
README.md
Normal file
1
README.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Binary counter on status LEDs `LED_OR`, `LED_GR`, and `LED_RD` using [libopencm3](https://github.com/libopencm3/libopencm3).
|
||||||
6
build.sh
Normal file
6
build.sh
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
make clean
|
||||||
|
mkdir -p build
|
||||||
|
bear -- make
|
||||||
137
flake.lock
generated
Normal file
137
flake.lock
generated
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-compat": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1767039857,
|
||||||
|
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gitignore": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"pre-commit-hooks",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1709087332,
|
||||||
|
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libopencm3-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1776882709,
|
||||||
|
"narHash": "sha256-P1MauqEzbra2asJf1uMU/7tUeAfYzYbyDltmbm86SLU=",
|
||||||
|
"owner": "libopencm3",
|
||||||
|
"repo": "libopencm3",
|
||||||
|
"rev": "fe769eef14a7930089d1cd729834facd589f5eee",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "libopencm3",
|
||||||
|
"repo": "libopencm3",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1778124196,
|
||||||
|
"narHash": "sha256-pYEytCNic/czazbV9r3tbQ6BZzqRBg/41x2dIC5ymOo=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "68a8af93ff4297686cb68880845e61e5e2e41d92",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre-commit-hooks": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1776796298,
|
||||||
|
"narHash": "sha256-PcRvlWayisPSjd0UcRQbhG8Oqw78AcPE6x872cPRHN8=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "pre-commit-hooks.nix",
|
||||||
|
"rev": "3cfd774b0a530725a077e17354fbdb87ea1c4aad",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "pre-commit-hooks.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"libopencm3-src": "libopencm3-src",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"pre-commit-hooks": "pre-commit-hooks",
|
||||||
|
"utils": "utils"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
159
flake.nix
Normal file
159
flake.nix
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "nixpkgs/nixpkgs-unstable";
|
||||||
|
utils.url = "github:numtide/flake-utils";
|
||||||
|
libopencm3-src = {
|
||||||
|
url = "github:libopencm3/libopencm3";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
|
pre-commit-hooks = {
|
||||||
|
url = "github:cachix/pre-commit-hooks.nix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
{
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
utils,
|
||||||
|
libopencm3-src,
|
||||||
|
pre-commit-hooks,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
overlays.default = final: prev: {
|
||||||
|
libopencm3-stm32g4 = final.stdenvNoCC.mkDerivation {
|
||||||
|
pname = "libopencm3-stm32g4";
|
||||||
|
version = "latest";
|
||||||
|
|
||||||
|
src = libopencm3-src;
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
patchShebangs scripts
|
||||||
|
'';
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
final.gcc-arm-embedded
|
||||||
|
final.python3
|
||||||
|
final.gnumake
|
||||||
|
];
|
||||||
|
|
||||||
|
enableParallelBuilding = true;
|
||||||
|
|
||||||
|
makeFlags = [
|
||||||
|
"PREFIX=arm-none-eabi-"
|
||||||
|
];
|
||||||
|
|
||||||
|
TARGETS = "stm32/g4";
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
mkdir -p $out
|
||||||
|
cp -r include lib mk scripts ld $out/
|
||||||
|
|
||||||
|
patchShebangs $out/scripts
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with final.lib; {
|
||||||
|
description = "Open source ARM Cortex-M microcontroller library (STM32G4 target)";
|
||||||
|
homepage = "http://libopencm3.org/";
|
||||||
|
license = licenses.lgpl3Plus;
|
||||||
|
platforms = platforms.all;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// utils.lib.eachDefaultSystem (
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
overlays = [ self.overlays.default ];
|
||||||
|
};
|
||||||
|
pname = "bincnt";
|
||||||
|
version = "0.1.0";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
packages = {
|
||||||
|
inherit (pkgs) libopencm3-stm32g4;
|
||||||
|
default = pkgs.stdenvNoCC.mkDerivation {
|
||||||
|
inherit pname version;
|
||||||
|
src = pkgs.lib.cleanSource ./.;
|
||||||
|
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
gcc-arm-embedded
|
||||||
|
gnumake
|
||||||
|
python3
|
||||||
|
];
|
||||||
|
|
||||||
|
makeFlags = [
|
||||||
|
"OPENCM3_DIR=${pkgs.libopencm3-stm32g4}"
|
||||||
|
"PREFIX=arm-none-eabi-"
|
||||||
|
];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp build/${pname}.elf $out/bin/
|
||||||
|
cp build/${pname}.bin $out/bin/
|
||||||
|
cp build/${pname}.hex $out/bin/
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
devShells.default =
|
||||||
|
let
|
||||||
|
# FIXME: 'gnu/stubs-32.h' file not found
|
||||||
|
clangdWrapper = pkgs.writeShellScriptBin "clangd" ''
|
||||||
|
exec ${pkgs.clang-tools}/bin/clangd \
|
||||||
|
--query-driver=${pkgs.gcc-arm-embedded}/bin/arm-none-eabi-* \
|
||||||
|
"$@"
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
pkgs.mkShell {
|
||||||
|
name = "stm32-blink";
|
||||||
|
packages = self.packages.${system}.default.nativeBuildInputs ++ [
|
||||||
|
clangdWrapper
|
||||||
|
|
||||||
|
pkgs.bear
|
||||||
|
pkgs.openocd
|
||||||
|
pkgs.stlink
|
||||||
|
];
|
||||||
|
OPENCM3_DIR = pkgs.libopencm3-stm32g4;
|
||||||
|
PREFIX = "arm-none-eabi-";
|
||||||
|
};
|
||||||
|
|
||||||
|
formatter =
|
||||||
|
let
|
||||||
|
inherit (self.checks.${system}.pre-commit-check.config) package configFile;
|
||||||
|
script = ''
|
||||||
|
${pkgs.lib.getExe package} run --all-files --config ${configFile}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
pkgs.writeShellScriptBin "pre-commit-run" script;
|
||||||
|
|
||||||
|
checks = {
|
||||||
|
build-packages = pkgs.linkFarm "flake-packages-${system}" self.packages.${system};
|
||||||
|
|
||||||
|
pre-commit-check = pre-commit-hooks.lib.${system}.run {
|
||||||
|
src = ./.;
|
||||||
|
hooks = {
|
||||||
|
nixfmt.enable = true;
|
||||||
|
clang-format = {
|
||||||
|
enable = true;
|
||||||
|
types_or = pkgs.lib.mkForce [
|
||||||
|
"c"
|
||||||
|
"c++"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
85
src/main.c
Normal file
85
src/main.c
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#include <libopencm3/cm3/systick.h>
|
||||||
|
#include <libopencm3/stm32/gpio.h>
|
||||||
|
#include <libopencm3/stm32/rcc.h>
|
||||||
|
|
||||||
|
#define LED_OR_PORT GPIOC
|
||||||
|
#define LED_OR_PIN GPIO10
|
||||||
|
|
||||||
|
#define LED_GR_PORT GPIOC
|
||||||
|
#define LED_GR_PIN GPIO11
|
||||||
|
|
||||||
|
#define LED_RD_PORT GPIOC
|
||||||
|
#define LED_RD_PIN GPIO12
|
||||||
|
|
||||||
|
#define COUNT_PERIOD_MS 500
|
||||||
|
|
||||||
|
static volatile uint32_t s_ticks = 0;
|
||||||
|
|
||||||
|
void sys_tick_handler(void) { s_ticks++; }
|
||||||
|
|
||||||
|
static void delay_ms(uint32_t ms) {
|
||||||
|
uint32_t until = s_ticks + ms;
|
||||||
|
while (s_ticks < until)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clock_setup(void) {
|
||||||
|
rcc_clock_setup_pll(&rcc_hsi_configs[RCC_CLOCK_3V3_170MHZ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void systick_setup(void) {
|
||||||
|
/* 1 ms tick at 170 MHz core clock */
|
||||||
|
systick_set_reload(rcc_ahb_frequency / 1000 - 1);
|
||||||
|
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
|
||||||
|
systick_counter_enable();
|
||||||
|
systick_interrupt_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gpio_setup(void) {
|
||||||
|
rcc_periph_clock_enable(RCC_GPIOC);
|
||||||
|
|
||||||
|
gpio_mode_setup(LED_OR_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_OR_PIN);
|
||||||
|
gpio_mode_setup(LED_GR_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_GR_PIN);
|
||||||
|
gpio_mode_setup(LED_RD_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_RD_PIN);
|
||||||
|
|
||||||
|
gpio_set_output_options(LED_OR_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_LOW,
|
||||||
|
LED_OR_PIN);
|
||||||
|
gpio_set_output_options(LED_GR_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_LOW,
|
||||||
|
LED_GR_PIN);
|
||||||
|
gpio_set_output_options(LED_RD_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_LOW,
|
||||||
|
LED_RD_PIN);
|
||||||
|
|
||||||
|
gpio_clear(LED_OR_PORT, LED_OR_PIN);
|
||||||
|
gpio_clear(LED_GR_PORT, LED_GR_PIN);
|
||||||
|
gpio_set(LED_RD_PORT, LED_RD_PIN); // active low
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gpio_write(uint32_t gpioport, uint16_t gpios, uint8_t value) {
|
||||||
|
if (value == 0) {
|
||||||
|
gpio_clear(gpioport, gpios);
|
||||||
|
} else {
|
||||||
|
gpio_set(gpioport, gpios);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_binary_counter(uint8_t value) {
|
||||||
|
gpio_write(LED_OR_PORT, LED_OR_PIN, value & 0x04);
|
||||||
|
gpio_write(LED_GR_PORT, LED_GR_PIN, value & 0x02);
|
||||||
|
gpio_write(LED_RD_PORT, LED_RD_PIN, value & 0x01);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
clock_setup();
|
||||||
|
systick_setup();
|
||||||
|
gpio_setup();
|
||||||
|
|
||||||
|
uint8_t counter = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
set_binary_counter(counter);
|
||||||
|
delay_ms(COUNT_PERIOD_MS);
|
||||||
|
counter++; // overflow is fine
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue