Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gd32v Support #21

Merged
merged 21 commits into from
Jul 24, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion build.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Some words on the build script here:
//! We cannot use a test runner here as we're building for freestanding.
//! This means we need to use addExecutable() instead of using
//! This means we need to use addExecutable() instead of using

const std = @import("std");
const microzig = @import("src/main.zig");
Expand All @@ -24,6 +24,8 @@ pub fn build(b: *std.build.Builder) !void {
BuildConfig{ .name = "boards.stm32f3discovery", .backing = Backing{ .board = boards.stm32f3discovery } },
BuildConfig{ .name = "boards.stm32f4discovery", .backing = Backing{ .board = boards.stm32f4discovery } },
BuildConfig{ .name = "boards.stm32f429idiscovery", .backing = Backing{ .board = boards.stm32f429idiscovery }, .supports_uart_test = false },
BuildConfig{ .name = "chips.gd32vf103x8", .backing = Backing{ .chip = chips.gd32vf103x8 } },
BuildConfig{ .name = "boards.longan_nano", .backing = Backing{ .board = boards.longan_nano } },
};

const Test = struct { name: []const u8, source: []const u8, uses_uart: bool = false, on_avr: bool = true };
Expand All @@ -42,6 +44,8 @@ pub fn build(b: *std.build.Builder) !void {
for (all_tests) |tst| {
if (tst.uses_uart and !cfg.supports_uart_test) continue;
if ((cfg.backing.getTarget().cpu_arch.?) == .avr and tst.on_avr == false) continue;
// Error: "gd32v - missing interrupts"
if ((cfg.backing.getTarget().cpu_arch.?) == .riscv32) continue;
kassane marked this conversation as resolved.
Show resolved Hide resolved

const exe = try microzig.addEmbeddedExecutable(
b,
Expand Down
6 changes: 6 additions & 0 deletions src/modules/boards.zig
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,9 @@ pub const stm32f429idiscovery = Board{
.path = root_path ++ "boards/stm32f429idiscovery/stm32f429idiscovery.zig",
.chip = chips.stm32f429zit6u,
};

pub const longan_nano = Board{
.name = "Longan Nano",
.path = root_path ++ "boards/longan-nano/longan-nano.zig",
.chip = chips.gd32vf103xb,
};
112 changes: 112 additions & 0 deletions src/modules/boards/longan-nano/longan-nano.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
pub const chip = @import("chip");
pub const micro = @import("microzig");

pub const cpu_frequency = 8_000_000; // 8 MHz

pub const pin_map = .{

// Port A
.PA0 = "PA0",
.PA1 = "PA1",
.PA2 = "PA2",
.PA3 = "PA3",
.PA4 = "PA4",
.PA5 = "PA5",
.PA6 = "PA6",
.PA7 = "PA7",
.PA8 = "PA8",
.PA9 = "PA9",
.PA10 = "PA10",
.PA11 = "PA11",
.PA12 = "PA12",
.PA13 = "PA13",

// Port B
.PB0 = "PB0",
.PB1 = "PB1",
.PB2 = "PB2",
.PB3 = "PB3",
.PB4 = "PB4",
.PB5 = "PB5",
.PB6 = "PB6",
.PB7 = "PB7",
.PB8 = "PB8",
.PB9 = "PB9",
.PB10 = "PB10",
.PB11 = "PB11",
.PB12 = "PB12",
.PB13 = "PB13",
.PB14 = "PB14",
.PB15 = "PB15",

// Port C
.PC0 = "PC0",
.PC1 = "PC1",
.PC2 = "PC2",
.PC3 = "PC3",
.PC4 = "PC4",
.PC5 = "PC5",
.PC6 = "PC6",
.PC7 = "PC7",
.PC8 = "PC8",
.PC9 = "PC9",
.PC10 = "PC10",
.PC11 = "PC11",
.PC12 = "PC12",
.PC13 = "PC13",
.PC14 = "PC14",
.PC15 = "PC15",

// Port D
.PD0 = "PD0",
.PD1 = "PD1",
.PD2 = "PD2",
.PD3 = "PD3",
.PD4 = "PD4",
.PD5 = "PD5",
.PD6 = "PD6",
.PD7 = "PD7",
.PD8 = "PD8",
.PD9 = "PD9",
.PD10 = "PD10",
.PD11 = "PD11",
.PD12 = "PD12",
.PD13 = "PD13",
.PD14 = "PD14",
.PD15 = "PD15",

// Port E
.PE0 = "PE0",
.PE1 = "PE1",
.PE2 = "PE2",
.PE3 = "PE3",
.PE4 = "PE4",
.PE5 = "PE5",
.PE6 = "PE6",
.PE7 = "PE7",
.PE8 = "PE8",
.PE9 = "PE9",
.PE10 = "PE10",
.PE11 = "PE11",
.PE12 = "PE12",
.PE13 = "PE13",
.PE14 = "PE14",
.PE15 = "PE15",

// Colors LED
// LCD_COLOR_WHITE 0xFFFF
// LCD_COLOR_BLACK 0x0000
// LCD_COLOR_GREY 0xF7DE
// LCD_COLOR_BLUE 0x001F
// LCD_COLOR_BLUE2 0x051F
// LCD_COLOR_RED 0xF800
// LCD_COLOR_MAGENTA 0xF81F
// LCD_COLOR_GREEN 0x07E0
// LCD_COLOR_CYAN 0x7FFF
// LCD_COLOR_YELLOW 0xFFE0
};

pub fn debugWrite(string: []const u8) void {
_ = string;
// TODO: implement
}
20 changes: 20 additions & 0 deletions src/modules/chips.zig
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ pub const lpc1768 = Chip{
},
};

pub const gd32vf103xb = Chip{
.name = "GD32VF103xB",
.path = root_path ++ "chips/gd32vf103/gd32vf103.zig",
.cpu = cpus.riscv32_imac,
.memory_regions = &.{
MemoryRegion{ .offset = 0x08000000, .length = 128 * 1024, .kind = .flash },
MemoryRegion{ .offset = 0x20000000, .length = 32 * 1024, .kind = .ram },
},
};

pub const gd32vf103x8 = Chip{
.name = "GD32VF103x8",
.path = root_path ++ "chips/gd32vf103/gd32vf103.zig",
.cpu = cpus.riscv32_imac,
.memory_regions = &.{
MemoryRegion{ .offset = 0x08000000, .length = 64 * 1024, .kind = .flash },
MemoryRegion{ .offset = 0x20000000, .length = 20 * 1024, .kind = .ram },
},
};

pub const stm32f103x8 = Chip{
.name = "STM32F103x8",
.path = root_path ++ "chips/stm32f103/stm32f103.zig",
Expand Down
114 changes: 114 additions & 0 deletions src/modules/chips/gd32vf103/gd32vf103.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
pub const cpu = @import("cpu");
pub const micro = @import("microzig");
pub const chip = @import("registers.zig");
const regs = chip.registers;

pub usingnamespace chip;

pub const clock_frequencies = .{
.cpu = 8_000_000, // 8 MHz
};

pub fn parsePin(comptime spec: []const u8) type {
const invalid_format_msg = "The given pin '" ++ spec ++ "' has an invalid format. Pins must follow the format \"P{Port}{Pin}\" scheme.";

if (spec[0] != 'P')
@compileError(invalid_format_msg);
if (spec[1] < 'A' or spec[1] > 'E')
@compileError(invalid_format_msg);

return struct {
const pin_number: comptime_int = @import("std").fmt.parseInt(u2, spec[2..], 10) catch @compileError(invalid_format_msg);
// 'A'...'E'
const gpio_port_name = spec[1..2];
const gpio_port = @field(regs, "GPIO" ++ gpio_port_name);
const suffix = @import("std").fmt.comptimePrint("{d}", .{pin_number});
};
}

fn setRegField(reg: anytype, comptime field_name: anytype, value: anytype) void {
var temp = reg.read();
@field(temp, field_name) = value;
reg.write(temp);
}

pub const gpio = struct {
pub fn setOutput(comptime pin: type) void {
_ = pin;
// TODO: check if pin is already configured as output
}
pub fn setInput(comptime pin: type) void {
_ = pin;
// TODO: check if pin is already configured as input
}

pub fn read(comptime pin: type) micro.gpio.State {
_ = pin;
// TODO: check if pin is configured as input
return .low;
}

pub fn write(comptime pin: type, state: micro.gpio.State) void {
_ = pin;
_ = state;
// TODO: check if pin is configured as output
}
};

pub const uart = struct {
pub const DataBits = enum(u2) {
five = 0,
six = 1,
seven = 2,
eight = 3,
};

pub const StopBits = enum(u1) {
one = 0,
two = 1,
};

pub const Parity = enum(u2) {
odd = 0,
even = 1,
mark = 2,
space = 3,
};
};

pub fn Uart(comptime index: usize, comptime pins: micro.uart.Pins) type {
if (pins.tx != null or pins.rx != null)
@compileError("TODO: custom pins are not currently supported");

return struct {
const UARTn = switch (index) {
0 => regs.UART3,
1 => regs.UART4,
else => @compileError("GD32VF103 has 2 UARTs available."),
};
const Self = @This();

pub fn init(config: micro.uart.Config) !Self {
_ = config;
return Self{};
}

pub fn canWrite(self: Self) bool {
_ = self;
return false;
}
pub fn tx(self: Self, ch: u8) void {
_ = ch;
while (!self.canWrite()) {} // Wait for Previous transmission
}

pub fn canRead(self: Self) bool {
_ = self;
return false;
}
pub fn rx(self: Self) u8 {
while (!self.canRead()) {} // Wait till the data is received
return 1; // Read received data
}
};
}
Loading