From 9a8f50d4963743e69f4287bc01349bcbd24cafff Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 27 Feb 2025 14:43:06 +0100 Subject: [PATCH] clean up and fix GPIO --- zynq-examples/src/main.rs | 2 +- zynq7000/bak/device.x | 4 - zynq7000/bak/example.svd | 753 ----------------------------------- zynq7000/bak/example.svd.tmp | 23 -- zynq7000/bak/gen-helper.sh | 42 -- zynq7000/src/gpio.rs | 148 +++++++ zynq7000/src/lib.rs | 128 +----- 7 files changed, 150 insertions(+), 950 deletions(-) delete mode 100644 zynq7000/bak/device.x delete mode 100644 zynq7000/bak/example.svd delete mode 100644 zynq7000/bak/example.svd.tmp delete mode 100755 zynq7000/bak/gen-helper.sh create mode 100644 zynq7000/src/gpio.rs diff --git a/zynq-examples/src/main.rs b/zynq-examples/src/main.rs index c59d190..31abe6a 100644 --- a/zynq-examples/src/main.rs +++ b/zynq-examples/src/main.rs @@ -19,7 +19,7 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! { #[unsafe(export_name = "main")] pub fn main() -> ! { - let mut gpio = unsafe { zynq7000::Gpio::new_mmio_fixed() }; + let mut gpio = unsafe { zynq7000::gpio::Gpio::new_mmio_fixed() }; gpio.modify_dirm_0(|v| v | ZEDBOARD_LED_MASK); gpio.modify_out_en_0(|v| v | ZEDBOARD_LED_MASK); loop { diff --git a/zynq7000/bak/device.x b/zynq7000/bak/device.x deleted file mode 100644 index 0bab52a..0000000 --- a/zynq7000/bak/device.x +++ /dev/null @@ -1,4 +0,0 @@ -PROVIDE(TIMER0 = DefaultHandler); -PROVIDE(TIMER1 = DefaultHandler); -PROVIDE(TIMER2 = DefaultHandler); - diff --git a/zynq7000/bak/example.svd b/zynq7000/bak/example.svd deleted file mode 100644 index 9e01310..0000000 --- a/zynq7000/bak/example.svd +++ /dev/null @@ -1,753 +0,0 @@ - - - - - - - - AMD - AMD - Zynq7000 - ARMCA9 - 1.0 - Community provided SVD file for the AMD Zynq7000 SoC - - - - CA9 - r1p0 - little - true - true - - 8 - 32 - - 32 - read-write - 0x00000000 - 0xFFFFFFFF - - - - - TIMER0 - 1.0 - 32 Timer / Counter, counting up or down from different sources - TIMER - 0x40010000 - 32 - read-write - - - 0 - 0x100 - registers - - - - TIMER0 - Timer 0 interrupt - 0 - - - - - - CR - Control Register - 0x00 - 32 - read-write - 0x00000000 - 0x1337F7F - - - - - EN - Enable - [0:0] - read-write - - - Disable - Timer is disabled and does not operate - 0 - - - Enable - Timer is enabled and can operate - 1 - - - - - - - RST - Reset Timer - [1:1] - write-only - - - No_Action - Write as ZERO if necessary - 0 - - - Reset_Timer - Reset the Timer - 1 - - - - - - - CNT - Counting direction - [3:2] - read-write - - - Count_UP - Timer Counts UO and wraps, if no STOP condition is set - 0 - - - Count_DOWN - Timer Counts DOWN and wraps, if no STOP condition is set - 1 - - - Toggle - Timer Counts up to MAX, then DOWN to ZERO, if no STOP condition is set - 2 - - - - - - - MODE - Operation Mode - [6:4] - read-write - - - Continous - Timer runs continously - 0 - - - Single_ZERO_MAX - Timer counts to 0x00 or 0xFFFFFFFF (depending on CNT) and stops - 1 - - - Single_MATCH - Timer counts to the Value of MATCH Register and stops - 2 - - - Reload_ZERO_MAX - Timer counts to 0x00 or 0xFFFFFFFF (depending on CNT), loads the RELOAD Value and continues - 3 - - - Reload_MATCH - Timer counts to the Value of MATCH Register, loads the RELOAD Value and continues - 4 - - - - - - - PSC - Use Prescaler - [7:7] - read-write - - - Disabled - Prescaler is not used - 0 - - - Enabled - Prescaler is used as divider - 1 - - - - - - - CNTSRC - Timer / Counter Source Divider - [11:8] - read-write - - - CAP_SRC - Capture Source is used directly - 0 - - - CAP_SRC_div2 - Capture Source is divided by 2 - 1 - - - CAP_SRC_div4 - Capture Source is divided by 4 - 2 - - - CAP_SRC_div8 - Capture Source is divided by 8 - 3 - - - CAP_SRC_div16 - Capture Source is divided by 16 - 4 - - - CAP_SRC_div32 - Capture Source is divided by 32 - 5 - - - CAP_SRC_div64 - Capture Source is divided by 64 - 6 - - - CAP_SRC_div128 - Capture Source is divided by 128 - 7 - - - CAP_SRC_div256 - Capture Source is divided by 256 - 8 - - - - - - - CAPSRC - Timer / Counter Capture Source - [15:12] - read-write - - - CClk - Core Clock - 0 - - - GPIOA_0 - GPIO A, PIN 0 - 1 - - - GPIOA_1 - GPIO A, PIN 1 - 2 - - - GPIOA_2 - GPIO A, PIN 2 - 3 - - - GPIOA_3 - GPIO A, PIN 3 - 4 - - - GPIOA_4 - GPIO A, PIN 4 - 5 - - - GPIOA_5 - GPIO A, PIN 5 - 6 - - - GPIOA_6 - GPIO A, PIN 6 - 7 - - - GPIOA_7 - GPIO A, PIN 7 - 8 - - - GPIOB_0 - GPIO B, PIN 0 - 9 - - - GPIOB_1 - GPIO B, PIN 1 - 10 - - - GPIOB_2 - GPIO B, PIN 2 - 11 - - - GPIOB_3 - GPIO B, PIN 3 - 12 - - - GPIOC_0 - GPIO C, PIN 0 - 13 - - - GPIOC_5 - GPIO C, PIN 1 - 14 - - - GPIOC_6 - GPIO C, PIN 2 - 15 - - - - - - - CAPEDGE - Capture Edge, select which Edge should result in a counter increment or decrement - [17:16] - read-write - - - RISING - Only rising edges result in a counter increment or decrement - 0 - - - FALLING - Only falling edges result in a counter increment or decrement - 1 - - - BOTH - Rising and falling edges result in a counter increment or decrement - 2 - - - - - - - TRGEXT - Triggers an other Peripheral - [21:20] - read-write - - - NONE - No Trigger is emitted - 0 - - - DMA1 - DMA Controller 1 is triggered, dependant on MODE - 1 - - - DMA2 - DMA Controller 2 is triggered, dependant on MODE - 2 - - - UART - UART is triggered, dependant on MODE - 3 - - - - - - - RELOAD - Select RELOAD Register n to reload Timer on condition - [25:24] - read-write - - - RELOAD0 - Selects Reload Register number 0 - 0 - - - RELOAD1 - Selects Reload Register number 1 - 1 - - - RELOAD2 - Selects Reload Register number 2 - 2 - - - RELOAD3 - Selects Reload Register number 3 - 3 - - - - - - - IDR - Selects, if Reload Register number is incremented, decremented or not modified - [27:26] - read-write - - - KEEP - Reload Register number does not change automatically - 0 - - - INCREMENT - Reload Register number is incremented on each match - 1 - - - DECREMENT - Reload Register number is decremented on each match - 2 - - - - - - - S - Starts and Stops the Timer / Counter - [31:31] - read-write - - - STOP - Timer / Counter is stopped - 0 - - - START - Timer / Counter is started - 1 - - - - - - - - - SR - Status Register - 0x04 - 16 - read-write - 0x00000000 - 0xD701 - - - - - RUN - Shows if Timer is running or not - [0:0] - read-only - - - Stopped - Timer is not running - 0 - - - Running - Timer is running - 1 - - - - - - - MATCH - Shows if the MATCH was hit - [8:8] - read-write - - - No_Match - The MATCH condition was not hit - 0 - - - Match_Hit - The MATCH condition was hit - 1 - - - - - - - UN - Shows if an underflow occured. This flag is sticky - [9:9] - read-write - - - No_Underflow - No underflow occured since last clear - 0 - - - Underflow - A minimum of one underflow occured since last clear - 1 - - - - - - - OV - Shows if an overflow occured. This flag is sticky - [10:10] - read-write - - - No_Overflow - No overflow occured since last clear - 0 - - - Overflow_occured - A minimum of one overflow occured since last clear - 1 - - - - - - - RST - Shows if Timer is in RESET state - [12:12] - read-only - - - Ready - Timer is not in RESET state and can operate - 0 - - - In_Reset - Timer is in RESET state and can not operate - 1 - - - - - - - RELOAD - Shows the currently active RELOAD Register - [15:14] - read-only - - - RELOAD0 - Reload Register number 0 is active - 0 - - - RELOAD1 - Reload Register number 1 is active - 1 - - - RELOAD2 - Reload Register number 2 is active - 2 - - - RELOAD3 - Reload Register number 3 is active - 3 - - - - - - - - - INT - Interrupt Register - 0x10 - 16 - read-write - 0x00000000 - 0x0771 - - - - - EN - Interrupt Enable - [0:0] - read-write - - - Disabled - Timer does not generate Interrupts - 0 - - - Enable - Timer triggers the TIMERn Interrupt - 1 - - - - - - - MODE - Interrupt Mode, selects on which condition the Timer should generate an Interrupt - [6:4] - read-write - - - Match - Timer generates an Interrupt when the MATCH condition is hit - 0 - - - Underflow - Timer generates an Interrupt when it underflows - 1 - - - Overflow - Timer generates an Interrupt when it overflows - 2 - - - - - - - - - COUNT - The Counter Register reflects the actual Value of the Timer/Counter - 0x20 - 32 - read-write - 0x00000000 - 0xFFFFFFFF - - - - - MATCH - The Match Register stores the compare Value for the MATCH condition - 0x24 - 32 - read-write - 0x00000000 - 0xFFFFFFFF - - - - - PRESCALE_RD - The Prescale Register stores the Value for the prescaler. The cont event gets divided by this value - 0x28 - 32 - read-only - 0x00000000 - 0xFFFFFFFF - - - - - PRESCALE_WR - The Prescale Register stores the Value for the prescaler. The cont event gets divided by this value - 0x28 - 32 - write-only - 0x00000000 - 0xFFFFFFFF - - - - - - 4 - 4 - RELOAD[%s] - The Reload Register stores the Value the COUNT Register gets reloaded on a when a condition was met. - 0x50 - 32 - read-write - 0x00000000 - 0xFFFFFFFF - - - - diff --git a/zynq7000/bak/example.svd.tmp b/zynq7000/bak/example.svd.tmp deleted file mode 100644 index a398a40..0000000 --- a/zynq7000/bak/example.svd.tmp +++ /dev/null @@ -1,23 +0,0 @@ - - - - TIMER1 - 0x40010100 - - TIMER1 - Timer 1 interrupt - 4 - - - - - - TIMER2 - 0x40010200 - - TIMER2 - Timer 2 interrupt - 6 - - - diff --git a/zynq7000/bak/gen-helper.sh b/zynq7000/bak/gen-helper.sh deleted file mode 100755 index 1b1dad4..0000000 --- a/zynq7000/bak/gen-helper.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - -# Use installed tool by default -svd2rust_bin="svd2rust" -# Automates the steps specified in https://docs.rs/svd2rust/0.19.0/svd2rust/ -if [ -f svd2rust ]; then - # If the local directory contains svd2rust, use that version instead - svd2rust_bin="./svd2rust" -elif [ -f ../svd2rust ]; then - # Keeps the repository clean - svd2rust_bin="../svd2rust" -fi -if [ -x "$(${svd2rust_bin} --version)" ]; then - echo "No svd2rust found locally or installed." \ - "Install it with cargo install svd2rust" - exit -fi - -if ! command -v form &> /dev/null -then - echo "form tool was not found" - exit 1 -fi - -if ! command -v svdtools &> /dev/null -then - echo "svdtools was not found" - exit 1 -fi - -# See https://github.com/rust-embedded/svd2rust/issues/830 for required re-export. -${svd2rust_bin} --target --reexport-interrupt --impl-defmt defmt --impl-debug-feature debug -i example.svd - -result=$? -if [ $result -ne 0 ]; then - echo "svd2rust failed with code $result" - exit -fi - -rm -rf src -form -i lib.rs -o src/ && rm lib.rs -cargo fmt diff --git a/zynq7000/src/gpio.rs b/zynq7000/src/gpio.rs new file mode 100644 index 0000000..0c70c56 --- /dev/null +++ b/zynq7000/src/gpio.rs @@ -0,0 +1,148 @@ +#[bitbybit::bitfield(u32)] +#[derive(Debug)] +pub struct MaskedOutput { + #[bits(16..=31, w)] + pub mask: u16, + #[bits(0..=15, rw)] + pub output: u16, +} + +#[derive(derive_mmio::Mmio)] +#[repr(C)] +pub struct Gpio { + /// Maskable output data (GPIO bank 0, MIO, lower 16 bits) + masked_out_0_lsw: MaskedOutput, + /// Maskable output data (GPIO bank 0, MIO, upper 16 bits) + masked_out_0_msw: MaskedOutput, + /// Maskable output data (GPIO bank 1, MIO, lower 16 bits) + masked_out_1_lsw: MaskedOutput, + /// Maskable output data (GPIO bank 1, MIO, upper 16 bits) + masked_out_1_msw: MaskedOutput, + /// Maskable output data (GPIO bank 2, EMIO, lower 16 bits) + masked_out_2_lsw: MaskedOutput, + /// Maskable output data (GPIO bank 2, EMIO, upper 16 bits) + masked_out_2_msw: MaskedOutput, + /// Maskable output data (GPIO bank 3, EMIO, lower 16 bits) + masked_out_3_lsw: MaskedOutput, + /// Maskable output data (GPIO bank 3, EMIO, upper 16 bits) + masked_out_3_msw: MaskedOutput, + + _reserved_0: [u32; 8], + + /// Output data (GPIO bank 0, MIO) + out_0: u32, + /// Output data (GPIO bank 1, MIO) + out_1: u32, + /// Output data (GPIO bank 2, EMIO) + out_2: u32, + /// Output data (GPIO bank 3, EMIO) + out_3: u32, + + _reserved_1: [u32; 4], + + /// Input data (GPIO bank 0, MIO) + in_0: u32, + /// Input data (GPIO bank 1, MIO) + in_1: u32, + /// Input data (GPIO bank 2, EMIO) + in_2: u32, + /// Input data (GPIO bank 3, EMIO) + in_3: u32, + + _reserved_2: [u32; 101], + + /// Direction mode (GPIO bank 0, MIO) + dirm_0: u32, + /// Output enable (GPIO bank 0, MIO) + out_en_0: u32, + /// Interrupt mask status (GPIO bank 0, MIO) + int_mask_0: u32, + /// Interrupt enable/unmask (GPIO bank 0, MIO) + int_en_0: u32, + /// Interrupt disable/mask (GPIO bank 0, MIO) + int_dis_0: u32, + /// Interrupt status (GPIO bank 0, MIO) + int_sts_0: u32, + /// Interrupt type (GPIO bank 0, MIO) + int_type_0: u32, + /// Interrupt polarity (GPIO bank 0, MIO) + int_pol_0: u32, + /// Interrupt any edge sensitivity (GPIO bank 0, MIO) + int_any_0: u32, + + _reserved_3: [u32; 7], + + /// Direction mode (GPIO bank 1, MIO) + dirm_1: u32, + /// Output enable (GPIO bank 1, MIO) + out_en_1: u32, + /// Interrupt mask status (GPIO bank 1, MIO) + int_mask_1: u32, + /// Interrupt enable/unmask (GPIO bank 1, MIO) + int_en_1: u32, + /// Interrupt disable/mask (GPIO bank 1, MIO) + int_dis_1: u32, + /// Interrupt status (GPIO bank 1, MIO) + int_sts_1: u32, + /// Interrupt type (GPIO bank 1, MIO) + int_type_1: u32, + /// Interrupt polarity (GPIO bank 1, MIO) + int_pol_1: u32, + /// Interrupt any edge sensitivity (GPIO bank 1, MIO) + int_any_1: u32, + + _reserved_4: [u32; 7], + + /// Direction mode (GPIO bank 2, MIO) + dirm_2: u32, + /// Output enable (GPIO bank 2, MIO) + outen_2: u32, + /// Interrupt mask status (GPIO bank 2, MIO) + int_mask_2: u32, + /// Interrupt enable/unmask (GPIO bank 2, MIO) + int_en_2: u32, + /// Interrupt disable/mask (GPIO bank 2, MIO) + int_dis_2: u32, + /// Interrupt status (GPIO bank 2, MIO) + int_sts_2: u32, + /// Interrupt type (GPIO bank 2, MIO) + int_type_2: u32, + /// Interrupt polarity (GPIO bank 2, MIO) + int_pol_2: u32, + /// Interrupt any edge sensitivity (GPIO bank 2, MIO) + int_any_2: u32, + + _reserved_5: [u32; 7], + + /// Direction mode (GPIO bank 3, MIO) + dirm_3: u32, + /// Output enable (GPIO bank 3, MIO) + outen_3: u32, + /// Interrupt mask status (GPIO bank 3, MIO) + int_mask_3: u32, + /// Interrupt enable/unmask (GPIO bank 3, MIO) + int_en_3: u32, + /// Interrupt disable/mask (GPIO bank 3, MIO) + int_dis_3: u32, + /// Interrupt status (GPIO bank 3, MIO) + int_sts_3: u32, + /// Interrupt type (GPIO bank 3, MIO) + int_type_3: u32, + /// Interrupt polarity (GPIO bank 3, MIO) + int_pol_3: u32, + /// Interrupt any edge sensitivity (GPIO bank 3, MIO) + int_any_3: u32, +} + +impl Gpio { + /// Create a new XGPIOPS GPIO MMIO instance. + /// + /// # Safety + /// + /// This API can be used to potentially create a driver to the same peripheral structure + /// from multiple threads. The user must ensure that concurrent accesses are safe and do not + /// interfere with each other. + pub unsafe fn new_mmio_fixed() -> MmioGpio { + unsafe { Self::new_mmio_at(0xE000A000) } + } +} diff --git a/zynq7000/src/lib.rs b/zynq7000/src/lib.rs index 997627f..45b7a36 100644 --- a/zynq7000/src/lib.rs +++ b/zynq7000/src/lib.rs @@ -1,130 +1,4 @@ //! Rust peripheral acess crate to the AMD Zynq 7000 SoCs #![no_std] -#[bitbybit::bitfield(u32)] -#[derive(Debug)] -pub struct MaskedOutput { - #[bits(16..=31, w)] - pub mask: u16, - #[bits(0..=15, rw)] - pub output: u16, -} - -#[derive(derive_mmio::Mmio)] -#[repr(C)] -pub struct Gpio { - /// Maskable output data (GPIO bank 0, MIO, lower 16 bits) - masked_out_0_lsw: MaskedOutput, - /// Maskable output data (GPIO bank 0, MIO, upper 16 bits) - masked_out_0_msw: MaskedOutput, - /// Maskable output data (GPIO bank 1, MIO, lower 16 bits) - masked_out_1_lsw: MaskedOutput, - /// Maskable output data (GPIO bank 1, MIO, upper 16 bits) - masked_out_1_msw: MaskedOutput, - /// Maskable output data (GPIO bank 2, EMIO, lower 16 bits) - masked_out_2_lsw: MaskedOutput, - /// Maskable output data (GPIO bank 2, EMIO, upper 16 bits) - masked_out_2_msw: MaskedOutput, - /// Maskable output data (GPIO bank 3, EMIO, lower 16 bits) - masked_out_3_lsw: MaskedOutput, - /// Maskable output data (GPIO bank 3, EMIO, upper 16 bits) - masked_out_3_msw: MaskedOutput, - - _reserved_0: [u32; 8], - - /// Output data (GPIO bank 0, MIO) - out_0: u32, - /// Output data (GPIO bank 1, MIO) - out_1: u32, - /// Output data (GPIO bank 2, EMIO) - out_2: u32, - /// Output data (GPIO bank 3, EMIO) - out_3: u32, - - _reserved_1: [u32; 4], - - /// Input data (GPIO bank 0, MIO) - in_0: u32, - /// Input data (GPIO bank 1, MIO) - in_1: u32, - /// Input data (GPIO bank 2, EMIO) - in_2: u32, - /// Input data (GPIO bank 3, EMIO) - in_3: u32, - - _reserved_2: [u32; 101], - - /// Direction mode (GPIO bank 0, MIO) - dirm_0: u32, - /// Output enable (GPIO bank 0, MIO) - out_en_0: u32, - /// Interrupt mask status (GPIO bank 0, MIO) - int_mask_0: u32, - /// Interrupt enable/unmask (GPIO bank 0, MIO) - int_en_0: u32, - /// Interrupt disable/mask (GPIO bank 0, MIO) - int_dis_0: u32, - /// Interrupt status (GPIO bank 0, MIO) - int_sts_0: u32, - /// Interrupt type (GPIO bank 0, MIO) - int_type_0: u32, - /// Interrupt polarity (GPIO bank 0, MIO) - int_pol_0: u32, - /// Interrupt any edge sensitivity (GPIO bank 0, MIO) - int_any_0: u32, - - _reserved_3: [u32; 8], - - /// Direction mode (GPIO bank 1, MIO) - dirm_1: u32, - /// Output enable (GPIO bank 1, MIO) - out_en_1: u32, - /// Interrupt mask status (GPIO bank 1, MIO) - int_mask_1: u32, - /// Interrupt enable/unmask (GPIO bank 1, MIO) - int_en_1: u32, - /// Interrupt disable/mask (GPIO bank 1, MIO) - int_dis_1: u32, - /// Interrupt status (GPIO bank 1, MIO) - int_sts_1: u32, - /// Interrupt type (GPIO bank 1, MIO) - int_type_1: u32, - /// Interrupt polarity (GPIO bank 1, MIO) - int_pol_1: u32, - /// Interrupt any edge sensitivity (GPIO bank 1, MIO) - int_any_1: u32, - - _reserved_4: [u32; 8], - - /// Direction mode (GPIO bank 2, MIO) - dirm_2: u32, - /// Output enable (GPIO bank 2, MIO) - outen_2: u32, - /// Interrupt mask status (GPIO bank 2, MIO) - int_mask_2: u32, - /// Interrupt enable/unmask (GPIO bank 2, MIO) - int_en_2: u32, - /// Interrupt disable/mask (GPIO bank 2, MIO) - int_dis_2: u32, - /// Interrupt status (GPIO bank 2, MIO) - int_sts_2: u32, - /// Interrupt type (GPIO bank 2, MIO) - int_type_2: u32, - /// Interrupt polarity (GPIO bank 2, MIO) - int_pol_2: u32, - /// Interrupt any edge sensitivity (GPIO bank 2, MIO) - int_any_2: u32, -} - -impl Gpio { - /// Create a new XGPIOPS GPIO MMIO instance. - /// - /// # Safety - /// - /// This API can be used to potentially create a driver to the same peripheral structure - /// from multiple threads. The user must ensure that concurrent accesses are safe and do not - /// interfere with each other. - pub unsafe fn new_mmio_fixed() -> MmioGpio { - unsafe { Self::new_mmio_at(0xE000A000) } - } -} +pub mod gpio;