Open pdgilbert opened 2 years ago
I don't have much experience in this area, but @allexoll on Element explained it for me:
the STM-rs dinamically create/link the correct memory.x depending on the mcu/reference you're choosing in your toml. since the ssd1306 crate also includes one memory.x for the STM32F103C8T6, it gets included twice in the linking process by build.rs. Since ssd1306 is a driver crate and not a mcu hal crate, it shouldn't include a memory.x linker script. when @pdgilbert was using your crate with (i suppose) another mcu-hal crate with no mechanism for memory.x, it was relying on yours for it. which would also probably explain his runtime error if it was for another mcu with another memory map.
https://github.com/stm32-rs/stm32l0xx-hal/blob/5e0d1946993d19f5ba51ab9698147b510ac1b7ef/build.rs#L71 for reference on how its done for stm32l0xx-hal
but that also mean that you might need to fix your crate/build.rs so it does not include this linker script (might break your example aswell, but there are other ways to have dev-depencencies)
It sounds like we need to remove memory.x
from this crate and rely on the one provided by stm32f1xx-hal if I'm not mistaken.
yes, usually, a device driver crate does not need a memory.x linker script.
Usually, it will be used like this:
my-project:
- my-mcu-hal (like stm32l0xx-hal)
- ssd1306
my-project
needs a memory map for the linker script. usually it can come from my-mcu-hal
or you can have a custom one in my-project
. stm32l0xx-hal
provides a disable-linker-script
for that purpose. ssd1306
does not need to provide one. If you have examples, they can have dev-depencencies for a specific example MCU, with the featureset needed to run that example.
I see that a dependency on stm32l0xx-hal
puts a memory.x
file in target/thumbv6m-none-eabi/debug/build/stm32l0xx-hal-.../out/memory.x
but near as I can tell no other device hals do that. (It seems like a good idea but is not very reliable unless they all do it.) Also @allexoll , could you please explain a bit more
If you have examples, they can have dev-depencencies for a specific example MCU, with the featureset needed to run that example.
I don't see how to use a dev-dependency to get the linker to find memory.x
. (Sorry, I'm still somewhat new to everything including cargo
, and I'm a bit slow.)
basically, you need one, and only one memory.x per executable (not per crate, per executable). Usually, this comes from either the hal, or you provide it yourself.
for example
stm32l0xx-hal
builds it dynamically, if you did not add the disable-linker-script
feature (lpc546xx-hal
does something similar)stm32f4xx-hal
provides a standard one in the repository, and asks you to copy it into your project folder (since their's is not included by build.rs
) and so does stm32f1xx-hal
(the memory.x used here).stm32f7xx-hal
provides multiple scripts that are included depending on the feature set.
and so on. memory.x
is dependent on your MCU since it defines the memory map of the device: where the flash starts and how big it is, where the ram starts, and how big it is, and so on.
adding this to a driver for a display does not make sense, since the driver is intended to be usable with different MCU, and therefore with different memory layouts.
If you want to have buildable and runnable example in this repository, you'll need to find a way to have it only included for those examples, and not for projects that include this driver, since it probably will be the wrong one for their MCU.
i think that could be either done in cargo/config (i think this is not used when used as a crate) with something like "linker-arg=Tmemory.x". in any case, having memory.x
included in build.rs (which does get used when the crate is used in a parent project) will cause issues for people using it.
I hope it's more clear now
Thanks @allexoll that is more clear. I see that with memory.x
, build.rs
and build.sh
removed the ssd1306
crate can be used properly. (It works and does not put a spurious memory.x
in place.) I still need to play a bit to see how to get ssd1306
to build its own examples on a specific MCU.
On a forked branch no_memory.x
I have removed the root memory.x
and the file build.sh
, added a directory memoryMaps
with memory.x
files for several different MCUs, and replaced the file build.rs
with a version that adds a link to a memory.x
file into the linker search path. The strategy for determining the link is described in the build.rs
file. The summary is that the crate can be built and used without putting a memory.x
file anywhere it might mistakenly be picked up, and the crate examples can be build with syntax:
# bluepill
cargo build --target thumbv7m-none-eabi
MEMMAP=stm32f103 cargo build --target thumbv7m-none-eabi --release --examples
MEMMAP=stm32f103 cargo build --target thumbv7m-none-eabi --release --example text_i2c
The examples in ssd1306
specify use stm32f1xx_hal
so above is what would be needed. For examples on other devices another MEMMAP
and target
can be set. I have been testing this with my own examples at https://github.com/pdgilbert/rust-integration-testing/actions.
Let me know if you want me to submit a PR.
ssd1306
in use (if applicable): current git versionDescription of the problem/feature request/other
I was stripping down my
Cargo.toml
to report a runtime problem with another crate and discovered that removing the unusedssd1306
gives me a linker problem compiling the example for a completely different crate:At first I thought the
ssd1306
build was "fixing" the link failure by copying a (STM32F103C8T6)memory.x
file from thessd1306
crate root into thetarget
directory. But deleting those does not "unfix" the linker, so I suspect something with the build scripts or probe-run. I can do the proper fix by providing the correctmemory.x
, but I would like to understand what is going on, and most importantly be sure I am getting the proper memory map on various MCUs.Any ideas?