From a8f578751ff3050edbd49cbeb7bbdddf0f3af6a5 Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Mon, 13 May 2024 00:16:24 +0200
Subject: [PATCH] tests/riscv32: workaround linking bug, update deps.

https://github.com/rust-embedded/riscv/issues/196
---
 tests/riscv32/Cargo.toml |   4 +-
 tests/riscv32/link.x     | 214 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 216 insertions(+), 2 deletions(-)
 create mode 100644 tests/riscv32/link.x

diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml
index 38fb2deec..94eda3c09 100644
--- a/tests/riscv32/Cargo.toml
+++ b/tests/riscv32/Cargo.toml
@@ -11,8 +11,8 @@ embassy-executor = { version = "0.5.0", path = "../../embassy-executor", feature
 embassy-time = { version = "0.3.0", path = "../../embassy-time" }
 embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
 
-riscv-rt = "0.11"
-riscv = { version = "0.10", features = ["critical-section-single-hart"] }
+riscv-rt = "0.12.2"
+riscv = { version = "0.11.1", features = ["critical-section-single-hart"] }
 
 
 [profile.dev]
diff --git a/tests/riscv32/link.x b/tests/riscv32/link.x
new file mode 100644
index 000000000..4076b0c68
--- /dev/null
+++ b/tests/riscv32/link.x
@@ -0,0 +1,214 @@
+/* # EMBASSY notes
+  This file is a workaround for https://github.com/rust-embedded/riscv/issues/196
+  Remove when fixed upstream.
+*/
+/* # Developer notes
+
+- Symbols that start with a double underscore (__) are considered "private"
+
+- Symbols that start with a single underscore (_) are considered "semi-public"; they can be
+  overridden in a user linker script, but should not be referred from user code (e.g. `extern "C" {
+  static mut _heap_size }`).
+
+- `EXTERN` forces the linker to keep a symbol in the final binary. We use this to make sure a
+  symbol if not dropped if it appears in or near the front of the linker arguments and "it's not
+  needed" by any of the preceding objects (linker arguments)
+
+- `PROVIDE` is used to provide default values that can be overridden by a user linker script
+
+- In this linker script, you may find symbols that look like `${...}` (e.g., `4`).
+  These are wildcards used by the `build.rs` script to adapt to different target particularities.
+  Check `build.rs` for more details about these symbols.
+
+- On alignment: it's important for correctness that the VMA boundaries of both .bss and .data *and*
+  the LMA of .data are all `4`-byte aligned. These alignments are assumed by the RAM
+  initialization routine. There's also a second benefit: `4`-byte aligned boundaries
+  means that you won't see "Address (..) is out of bounds" in the disassembly produced by `objdump`.
+*/
+
+PROVIDE(_stext = ORIGIN(REGION_TEXT));
+PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
+PROVIDE(_max_hart_id = 0);
+PROVIDE(_hart_stack_size = 2K);
+PROVIDE(_heap_size = 0);
+
+PROVIDE(InstructionMisaligned = ExceptionHandler);
+PROVIDE(InstructionFault = ExceptionHandler);
+PROVIDE(IllegalInstruction = ExceptionHandler);
+PROVIDE(Breakpoint = ExceptionHandler);
+PROVIDE(LoadMisaligned = ExceptionHandler);
+PROVIDE(LoadFault = ExceptionHandler);
+PROVIDE(StoreMisaligned = ExceptionHandler);
+PROVIDE(StoreFault = ExceptionHandler);;
+PROVIDE(UserEnvCall = ExceptionHandler);
+PROVIDE(SupervisorEnvCall = ExceptionHandler);
+PROVIDE(MachineEnvCall = ExceptionHandler);
+PROVIDE(InstructionPageFault = ExceptionHandler);
+PROVIDE(LoadPageFault = ExceptionHandler);
+PROVIDE(StorePageFault = ExceptionHandler);
+
+PROVIDE(SupervisorSoft = DefaultHandler);
+PROVIDE(MachineSoft = DefaultHandler);
+PROVIDE(SupervisorTimer = DefaultHandler);
+PROVIDE(MachineTimer = DefaultHandler);
+PROVIDE(SupervisorExternal = DefaultHandler);
+PROVIDE(MachineExternal = DefaultHandler);
+
+PROVIDE(DefaultHandler = DefaultInterruptHandler);
+PROVIDE(ExceptionHandler = DefaultExceptionHandler);
+
+/* # Pre-initialization function */
+/* If the user overrides this using the `#[pre_init]` attribute or by creating a `__pre_init` function,
+   then the function this points to will be called before the RAM is initialized. */
+PROVIDE(__pre_init = default_pre_init);
+
+/* A PAC/HAL defined routine that should initialize custom interrupt controller if needed. */
+PROVIDE(_setup_interrupts = default_setup_interrupts);
+
+/* # Multi-processing hook function
+   fn _mp_hook() -> bool;
+
+   This function is called from all the harts and must return true only for one hart,
+   which will perform memory initialization. For other harts it must return false
+   and implement wake-up in platform-dependent way (e.g. after waiting for a user interrupt).
+*/
+PROVIDE(_mp_hook = default_mp_hook);
+
+/* # Start trap function override
+  By default uses the riscv crates default trap handler
+  but by providing the `_start_trap` symbol external crates can override.
+*/
+PROVIDE(_start_trap = default_start_trap);
+
+SECTIONS
+{
+  .text.dummy (NOLOAD) :
+  {
+    /* This section is intended to make _stext address work */
+    . = ABSOLUTE(_stext);
+  } > REGION_TEXT
+
+  .text _stext :
+  {
+    /* Put reset handler first in .text section so it ends up as the entry */
+    /* point of the program. */
+    KEEP(*(.init));
+    KEEP(*(.init.rust));
+    . = ALIGN(4);
+    *(.trap);
+    *(.trap.rust);
+    *(.text.abort);
+    *(.text .text.*);
+  } > REGION_TEXT
+
+  .eh_frame : { KEEP(*(.eh_frame)) } > REGION_TEXT
+  .eh_frame_hdr : { *(.eh_frame_hdr) } > REGION_TEXT
+
+  .rodata : ALIGN(4)
+  {
+    *(.srodata .srodata.*);
+    *(.rodata .rodata.*);
+
+    /* 4-byte align the end (VMA) of this section.
+       This is required by LLD to ensure the LMA of the following .data
+       section will have the correct alignment. */
+    . = ALIGN(4);
+  } > REGION_RODATA
+
+  .data : ALIGN(4)
+  {
+    _sidata = LOADADDR(.data);
+    _sdata = .;
+    /* Must be called __global_pointer$ for linker relaxations to work. */
+    PROVIDE(__global_pointer$ = . + 0x800);
+    *(.sdata .sdata.* .sdata2 .sdata2.*);
+    *(.data .data.*);
+    . = ALIGN(4);
+    _edata = .;
+  } > REGION_DATA AT > REGION_RODATA
+
+  .bss (NOLOAD) : ALIGN(4)
+  {
+    _sbss = .;
+    *(.sbss .sbss.* .bss .bss.*);
+    . = ALIGN(4);
+    _ebss = .;
+  } > REGION_BSS
+
+  /* fictitious region that represents the memory available for the heap */
+  .heap (NOLOAD) :
+  {
+    _sheap = .;
+    . += _heap_size;
+    . = ALIGN(4);
+    _eheap = .;
+  } > REGION_HEAP
+
+  /* fictitious region that represents the memory available for the stack */
+  .stack (NOLOAD) :
+  {
+    _estack = .;
+    . = ABSOLUTE(_stack_start);
+    _sstack = .;
+  } > REGION_STACK
+
+  /* fake output .got section */
+  /* Dynamic relocations are unsupported. This section is only used to detect
+     relocatable code in the input files and raise an error if relocatable code
+     is found */
+  .got (INFO) :
+  {
+    KEEP(*(.got .got.*));
+  }
+}
+
+/* Do not exceed this mark in the error messages above                                    | */
+ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
+ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
+
+ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, "
+ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
+
+ASSERT(ORIGIN(REGION_DATA) % 4 == 0, "
+ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned");
+
+ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
+ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
+
+ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
+ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
+
+ASSERT(ORIGIN(REGION_STACK) % 4 == 0, "
+ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned");
+
+ASSERT(_stext % 4 == 0, "
+ERROR(riscv-rt): `_stext` must be 4-byte aligned");
+
+ASSERT(_sdata % 4 == 0 && _edata % 4 == 0, "
+BUG(riscv-rt): .data is not 4-byte aligned");
+
+ASSERT(_sidata % 4 == 0, "
+BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
+
+ASSERT(_sbss % 4 == 0 && _ebss % 4 == 0, "
+BUG(riscv-rt): .bss is not 4-byte aligned");
+
+ASSERT(_sheap % 4 == 0, "
+BUG(riscv-rt): start of .heap is not 4-byte aligned");
+
+ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
+ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
+Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
+
+ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, "
+ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts.
+Consider changing `_max_hart_id` or `_hart_stack_size`.");
+
+ASSERT(SIZEOF(.got) == 0, "
+.got section detected in the input files. Dynamic relocations are not
+supported. If you are linking to C code compiled using the `gcc` crate
+then modify your build script to compile the C code _without_ the
+-fPIC flag. See the documentation of the `gcc::Config.fpic` method for
+details.");
+
+/* Do not exceed this mark in the error messages above                                    | */