diff --git a/tools/regz/.github/pull_request_template.md b/tools/regz/.github/pull_request_template.md new file mode 100644 index 0000000..6a7ef6b --- /dev/null +++ b/tools/regz/.github/pull_request_template.md @@ -0,0 +1,5 @@ +### Issue + +# + +### Description diff --git a/tools/regz/.github/workflows/ci.yml b/tools/regz/.github/workflows/ci.yml new file mode 100644 index 0000000..f2bcb9c --- /dev/null +++ b/tools/regz/.github/workflows/ci.yml @@ -0,0 +1,150 @@ +name: ci +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + schedule: + - cron: "0 7 * * *" + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + target: [ + #riscv64-linux-gnu, + #riscv64-linux-musl, + aarch64-linux-gnu, + aarch64-linux-musl, + aarch64-macos, + i386-linux-gnu, + i386-linux-musl, + #i386-windows, + x86_64-linux-gnu, + x86_64-linux-musl, + x86_64-macos, + #x86_64-windows-gnu, + ] + mode: [ + debug, + release-safe, + release-fast, + release-small, + ] + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + fetch-depth: 0 + + - name: Setup Zig + uses: goto-bus-stop/setup-zig@v1.3.0 + with: + version: master + + - name: Build Debug + if: ${{ matrix.mode == 'debug' }} + run: zig build -Dtarget=${{ matrix.target }} + + - name: Build Release + if: ${{ matrix.mode != 'debug' }} + run: zig build -D${{ matrix.mode }} -Dtarget=${{ matrix.target }} + + test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ + ubuntu-latest, + #windows-latest, + macos-latest, + ] + mode: [ + debug, + release-safe, + release-fast, + release-small, + ] + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + fetch-depth: 0 + + - name: Setup Zig + uses: goto-bus-stop/setup-zig@v1.3.0 + with: + version: master + + - name: Build and Test Debug + if: ${{ matrix.mode == 'debug' }} + run: zig build test + + - name: Build and Test Release + if: ${{ matrix.mode != 'debug' }} + run: zig build test -D${{ matrix.mode }} + + #crosscompile-from-windows: + # runs-on: windows-latest + # strategy: + # matrix: + # target: [ + # #riscv64-linux-gnu, + # #riscv64-linux-musl, + # aarch64-linux-gnu, + # aarch64-linux-musl, + # aarch64-macos, + # i386-linux-gnu, + # i386-linux-musl, + # x86_64-linux-gnu, + # x86_64-linux-musl, + # x86_64-macos, + # ] + # steps: + # - name: Checkout + # uses: actions/checkout@v2 + # with: + # submodules: recursive + # fetch-depth: 0 + + # - name: Setup Zig + # uses: goto-bus-stop/setup-zig@v1.3.0 + # with: + # version: master + + # - name: Build + # run: zig build + + crosscompile-from-macos: + runs-on: macos-latest + strategy: + matrix: + target: [ + #riscv64-linux-gnu, + #riscv64-linux-musl, + aarch64-linux-gnu, + aarch64-linux-musl, + i386-linux-gnu, + i386-linux-musl, + #i386-windows, + x86_64-linux-gnu, + x86_64-linux-musl, + #x86_64-windows-gnu, + ] + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + fetch-depth: 0 + + - name: Setup Zig + uses: goto-bus-stop/setup-zig@v1.3.0 + with: + version: master + + - name: Build + run: zig build diff --git a/tools/regz/build.zig b/tools/regz/build.zig index 0b88ec5..4c3ea10 100644 --- a/tools/regz/build.zig +++ b/tools/regz/build.zig @@ -38,10 +38,14 @@ pub fn build(b: *std.build.Builder) !void { const run_step = b.step("run", "Run the app"); run_step.dependOn(&run_cmd.step); - const exe_tests = b.addTest("src/main.zig"); - exe_tests.setTarget(target); - exe_tests.setBuildMode(mode); + const tests = b.addTest("tests/main.zig"); + tests.setTarget(target); + tests.setBuildMode(mode); + tests.addOptions("build_options", build_options); + tests.addPackagePath("xml", "src/xml.zig"); + tests.addPackagePath("Database", "src/Database.zig"); + xml.link(tests); const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&exe_tests.step); + test_step.dependOn(&tests.step); } diff --git a/tools/regz/src/Database.zig b/tools/regz/src/Database.zig index 359931a..b18d60f 100644 --- a/tools/regz/src/Database.zig +++ b/tools/regz/src/Database.zig @@ -687,6 +687,7 @@ pub fn toZig(self: *Self, writer: anytype) !void { try writer.print( \\// this file was generated by regz: https://github.com/ZigEmbeddedGroup/regz \\// commit: {s} + \\ , .{build_options.commit}); try writer.writeAll("//\n"); if (self.device.?.vendor) |vendor_name| diff --git a/tools/regz/src/xml.zig b/tools/regz/src/xml.zig index 40dfd30..2b86c7d 100644 --- a/tools/regz/src/xml.zig +++ b/tools/regz/src/xml.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const c = @cImport({ +pub const c = @cImport({ @cDefine("LIBXML_TREE_ENABLED", {}); @cDefine("LIBXML_SCHEMAS_ENABLED", {}); @cDefine("LIBXML_READER_ENABLED", {}); @@ -16,6 +16,10 @@ pub const cleanupParser = c.xmlCleanupParser; pub const freeDoc = c.xmlFreeDoc; pub const docGetRootElement = c.xmlDocGetRootElement; +pub fn readFromMemory(text: []const u8) !*Doc { + return c.xmlReadMemory(text.ptr, @intCast(c_int, text.len), null, null, 0) orelse error.XmlReadMemory; +} + pub fn getAttribute(node: ?*Node, key: [:0]const u8) ?[]const u8 { if (c.xmlHasProp(node, key.ptr)) |prop| { if (@ptrCast(*c.xmlAttr, prop).children) |value_node| { diff --git a/tools/regz/tests/atdf.zig b/tools/regz/tests/atdf.zig new file mode 100644 index 0000000..495b7b3 --- /dev/null +++ b/tools/regz/tests/atdf.zig @@ -0,0 +1,3 @@ +test "atdf empty" { + // please remove and do a real test +} diff --git a/tools/regz/tests/main.zig b/tools/regz/tests/main.zig new file mode 100644 index 0000000..adb141a --- /dev/null +++ b/tools/regz/tests/main.zig @@ -0,0 +1,4 @@ +test "" { + _ = @import("svd.zig"); + _ = @import("atdf.zig"); +} diff --git a/tools/regz/tests/svd.zig b/tools/regz/tests/svd.zig new file mode 100644 index 0000000..2bccaf4 --- /dev/null +++ b/tools/regz/tests/svd.zig @@ -0,0 +1,18 @@ +const std = @import("std"); +const xml = @import("xml"); +const Database = @import("Database"); + +const allocator = std.testing.allocator; +const expectEqual = std.testing.expectEqual; + +test "cmsis example" { + const text = @embedFile("svd/cmsis-example.svd"); + const doc: *xml.Doc = try xml.readFromMemory(text); + defer xml.freeDoc(doc); + + var db = try Database.initFromSvd(allocator, doc); + defer db.deinit(); + + // CPU is not populated in this svd file + try expectEqual(@as(@TypeOf(db.cpu), null), db.cpu); +} diff --git a/tools/regz/tests/svd/cmsis-example.svd b/tools/regz/tests/svd/cmsis-example.svd new file mode 100644 index 0000000..03db1d4 --- /dev/null +++ b/tools/regz/tests/svd/cmsis-example.svd @@ -0,0 +1,739 @@ + + + + + + + + ARMCM3xxx + 1.0 + ARM 32-bit Cortex-M3 Microcontroller based device, CPU clock up to 80MHz, etc. + 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 + 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 + + + Reserved + 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 + 0,1,2,3 + 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 + + + + + + + TIMER1 + 0x40010100 + + TIMER1 + 4 + + + + + + TIMER2 + 0x40010200 + + TIMER2 + 6 + + + +