zig-riscv-embedded

Experimental Zig-based CoAP node for the HiFive1 RISC-V board

git clone https://git.8pit.net/zig-riscv-embedded.git

 1// Copyright © 2021 Sören Tempel
 2//
 3// This program is free software: you can redistribute it and/or modify
 4// it under the terms of the GNU Affero General Public License as
 5// published by the Free Software Foundation, either version 3 of the
 6// License, or (at your option) any later version.
 7//
 8// This program is distributed in the hope that it will be useful, but
 9// WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11// Affero General Public License for more details.
12//
13// You should have received a copy of the GNU Affero General Public License
14// along with this program. If not, see <https://www.gnu.org/licenses/>.
15
16// Maximum of 32 pins -> 2**5 = 32.
17pub const Pin = u5;
18
19pub const Mode = enum {
20    IN,
21    OUT,
22};
23
24pub fn pin(x: Pin, y: Pin) Pin {
25    return x | y;
26}
27
28pub const Gpio = struct {
29    base_addr: usize,
30
31    const Reg = enum(usize) {
32        input = 0x04,
33        output_en = 0x08,
34        output_val = 0x0c,
35        pue = 0x10,
36        iof_en = 0x38,
37        iof_sel = 0x3c,
38    };
39
40    fn readWord(self: Gpio, reg: Reg) u32 {
41        const ptr = @intToPtr(*volatile u32, self.base_addr + @enumToInt(reg));
42        return ptr.*;
43    }
44
45    fn writeWord(self: Gpio, reg: Reg, value: u32) void {
46        const ptr = @intToPtr(*volatile u32, self.base_addr + @enumToInt(reg));
47        ptr.* = value;
48    }
49
50    pub fn setRegister(self: Gpio, reg: Reg, x: Pin, val: u1) void {
51        const regVal = self.readWord(reg);
52
53        const mask = @as(u32, 1) << x;
54        if (val == 0) {
55            self.writeWord(reg, regVal & ~mask);
56        } else {
57            self.writeWord(reg, regVal | mask);
58        }
59    }
60
61    // Configure a GPIO pin as IOF controlled (instead of software controlled).
62    pub fn setIOFCtrl(self: Gpio, x: Pin, select: u1) void {
63        // Select one of the two HW-Driven functions.
64        self.setRegister(Reg.iof_sel, x, select);
65
66        // Enable selected HW-Driven function.
67        self.setRegister(Reg.iof_en, x, 1);
68    }
69
70    pub fn set(self: Gpio, x: Pin, v: u1) void {
71        self.setRegister(Reg.output_val, x, v);
72    }
73
74    pub fn init(self: Gpio, x: Pin, mode: Mode) void {
75        switch (mode) {
76            Mode.IN => {
77                self.setRegister(Reg.input, x, 1);
78                self.setRegister(Reg.output_en, x, 0);
79                self.setRegister(Reg.pue, x, 0);
80            },
81            Mode.OUT => {
82                self.setRegister(Reg.input, x, 0);
83                self.setRegister(Reg.output_en, x, 1);
84                self.setRegister(Reg.pue, x, 0);
85            },
86        }
87
88        // Disable HW-driven functions for Pin
89        self.setRegister(Reg.iof_en, x, 0);
90        self.setRegister(Reg.iof_sel, x, 0);
91    }
92};