diff --git a/build.rs b/build.rs
index 52b4fde..ac5ffc3 100644
--- a/build.rs
+++ b/build.rs
@@ -117,4 +117,53 @@ fn main() {
     for module in known_modules {
         println!("cargo::rustc-check-cfg=cfg(riot_module_{})", module);
     }
+
+    // As a means of last resort, we emulate cfg(accessible(::path::to::thing)), as a
+    // workaround for https://github.com/rust-lang/rust/issues/64797
+    //
+    // This is sometimes necessary when some C API compatible change (eg. renaming a field with a
+    // deprecated union while introducing a proper accessor, as done in
+    // https://github.com/RIOT-OS/RIOT/pull/20900) leads to changes in bindgen and c2rust outputs.
+    //
+    // This is similar to the markers that were previously used in riot-sys. We access files
+    // directly to avoid going through `links=` (see also
+    // <https://github.com/RIOT-OS/rust-riot-sys/pull/38>). This
+    //
+    // * limits the impact of source changes (this way, only changs to relevant headerst trigger
+    //   a rebuild of riot-wrappers), and
+    // * removes the need for lock-stepping riot-sys and riot-wrappers.
+    //
+    // The downside of the tighter coupling with the paths in RIOT is reduced by keeping things
+    // local and the stabiity structure: All these access checks can be removed once riot-wrappers
+    // stops supporting a RIOT version that has the symbol unconditionally, without any concern for
+    // compatibility between crates (as the cfgs are just internal).
+
+    let riotbase: std::path::PathBuf = env::var("RIOTBASE")
+        .expect("No RIOTBASE set, can not inspect source files for symbol presence.")
+        .into();
+    println!("cargo:rerun-if-env-changed=RIOTBASE");
+
+    let emulate_accessible = [
+        // It's a static inline function and riot-sys currently only gives the file for the bindgen
+        // output, not the c2rust output. Using coap_build_udp_hdr presence as a stand-in.
+        //
+        // Remove this after a release including coap_pkt_set_code
+        // <https://github.com/RIOT-OS/riot/issues/20900> has been published.
+        (
+            &"inline_coap_pkt_set_code",
+            &"sys/include/net/nanocoap.h",
+            &"coap_pkt_set_code",
+        ),
+    ];
+
+    for (rust_name, header_file, header_search_string) in emulate_accessible {
+        let header_file = riotbase.join(header_file);
+        println!("cargo:rerun-if-changed={}", header_file.display());
+        let header_code =
+            std::fs::read_to_string(&header_file).expect("Failed to read header file");
+        println!("cargo:rustc-check-cfg=cfg(accessible_riot_sys_{rust_name})");
+        if header_code.contains(header_search_string) {
+            println!("cargo:rustc-cfg=accessible_riot_sys_{rust_name}");
+        }
+    }
 }
diff --git a/src/gcoap.rs b/src/gcoap.rs
index d7dddf5..fc1267e 100644
--- a/src/gcoap.rs
+++ b/src/gcoap.rs
@@ -380,7 +380,16 @@ impl<'b> PacketBuffer<'b> {
     }
 
     pub fn set_code_raw(&mut self, code: u8) {
-        unsafe { (*(*self.pkt).hdr).code = code };
+        #[cfg(accessible_riot_sys_inline_coap_pkt_set_code)]
+        {
+            unsafe {
+                riot_sys::inline::coap_pkt_set_code(crate::inline_cast_ref_mut(self.pkt), code)
+            };
+        }
+        #[cfg(not(accessible_riot_sys_inline_coap_pkt_set_code))]
+        {
+            unsafe { (*(*self.pkt).hdr).code = code };
+        }
     }
 
     /// Return the total number of bytes in the message, given that `payload_used` bytes were
diff --git a/src/gnrc/netreg.rs b/src/gnrc/netreg.rs
index 0cf7e1d..b284389 100644
--- a/src/gnrc/netreg.rs
+++ b/src/gnrc/netreg.rs
@@ -30,7 +30,7 @@ type PktsnipPort = crate::msg::v2::SendPort<
 ///
 /// It might be convenient for this to return at some point (in case of short-lived network
 /// services). Deregistration could be done and everything returned alright -- but the grant would
-/// still be lost. This could be mitigated by accepting a 'static PktsnipPort or a clonable version
+/// still be lost. This could be mitigated by accepting a 'static PktsnipPort or a cloneable version
 /// thereof -- not that anything could still be recombined after that, but at least it could be
 /// used once more (with the risk that messages from the old registration arrive in the new one,
 /// which is wrong correctness-wise but safe because it'll still be a pointer to a pktsnip).
diff --git a/src/msg/v2.rs b/src/msg/v2.rs
index 05bcec6..6c21e38 100644
--- a/src/msg/v2.rs
+++ b/src/msg/v2.rs
@@ -74,7 +74,7 @@ pub struct ReceivePort<TYPE: Send, const TYPENO: u16> {
 /// share a shared reference), it would be possible to create a version of the SendPort
 /// that counts its clones at runtime and can only be returned when all of them are recombined, or
 /// just to create a version that can be cloned at will but never recombined any more. (One way to
-/// do the latter would be to add a const boolean type parameter "CLONED"; a `.clonable(self) ->
+/// do the latter would be to add a const boolean type parameter "CLONED"; a `.cloneable(self) ->
 /// Self` would switch that from false to true, and then copy and clone would be implemented for
 /// the result, whereas recombination would only be implemented for the CLONED = false version).
 pub struct SendPort<TYPE: Send, const TYPENO: u16> {