rust-embedded/cortex-m

Release new version?

Opened this issue ยท 18 comments

The cortex-m crates on crates.io seem to be quite outdated. For example the last release of cortex-m was over 2 years ago and includes the deprecated bare-metal critical section.

It would be nice to get a new release of the master branch at some point.

The contents of the main branch are a breaking change, and we don't want to release a breaking change right now. We're going to backport the non-breaking changes and do a new 0.7.x release as soon as someone has free time.

When will you release the breaking changes then? It seems to me that the sooner it gets released the better. Easier to make changes while the ecosystem is younger.

TBD. A breaking change in this crate splits the ecosystem due to its implementation of critical-section for single-core CPUs, so it causes everyone a lot of pain and must be carefully managed.

TBD. A breaking change in this crate splits the ecosystem due to its implementation of critical-section for single-core CPUs, so it causes everyone a lot of pain and must be carefully managed.

That's fair. It just feels like the current situation is worse. You know the breaking change has to come eventually but you don't know when so you can't plan for it and the longer you wait the more crates there are that depend on the old version and will suffer once the breaking change actually happens.

Has there been some decision on this? I noticed that all the breaking changes on master got reverted.

We plan to release 0.7.8 soon with as many back-ported changes as possible; the plan for 0.8 or 1.0 with breaking changes is less clear atm.

I noticed y'all are starting to pull in embedded-hal 1.0. Is there anything I can help with that upgrade? Also, is that planned to be incorporated with the 0.7.8 release?

TBD. A breaking change in this crate splits the ecosystem

To me, the ecosystem has already split since the release of version 1.0 of embedded-hal. One of the crates that poses dependency issues is cortex-m, because it relies on pre-1.0 releases of embedded-hal.

A breaking change in this crate splits the ecosystem due to its implementation of critical-section for single-core CPUs, so it causes everyone a lot of pain and must be carefully managed.

I thought about this and I actually don't see the problem. The critical section implementation is an optional feature, so you would only enable it for one version of cortex-m and there would be no issue.

To me, the ecosystem has already split since the release of version 1.0 of embedded-hal. One of the crates that poses dependency issues is cortex-m, because it relies on pre-1.0 releases of embedded-hal.

This is an annoyance. Using modern crates that use embedded-hal 1.0 and still needing to use cortex-m that is on an older version is really a pain. I agree that this out of date issue is beginning to cause a split in ecosystems.

I can assure you that the maintainers are acutely aware of any annoyances to be found in our current solution. If it was easy to fix, we'd have fixed it already.

When we say "ecosystem splitting", it has a specific meaning. Having two copies of the embedded-hal crate in your dependency tree is not "ecosystem-splitting" and, whilst sub-optimal, is supported and does work correctly.

Briefly, the issue is (and I may not have 100% of the nuance here, but I'm sure @adamgreig will jump in to correct me):

  1. PACs generated with svd2rust implement the cortex_m::interrupt::InterruptNumber trait
  2. PACs currently depend upon cortex-m = "0.7.3" and so will not select cortex-m 0.8
  3. Functions like cortex_m::peripheral::NVIC::mask use I: InterruptNumber
  4. If we release a cortex-m version 0.8, you would not be able to use cortex_m::peripheral::NVIC::mask with an interrupt from a PAC using version 0.7, because cortex_m@0.7.3::interrupt::InterruptNumber is a completely different trait to cortex_m@0.8.0::interrupt::InterruptNumber
  5. The cortex-m crate gives you access to singleton objects that represent the Cortex-M peripherals, like the SysTick or the NVIC, via the Peripherals struct
  6. Having two versions of the cortex-m crate in your tree would let you create two copies of the singleton objects (one from each version), breaking our safety model for the use of these objects and potentially allowing for undefined behaviour
  7. You cannot have two versions of a crate in your tree if that crate has the links = property
  8. We deliberately mark the cortex-m crate as having a links = property in its Cargo.toml to stop you from doing point 6, and to avoid confusion with point 4.

So, if we put out a breaking change release of cortex-m, there would be some PACs still using cortex-m 0.7 and anyone using those PACs would have to use cortex-m 0.7, whilst other PACs might be using cortex-m 0.8 and anyone use one of those PACs would have to use cortex-m 0.8. Any library crate that wanted to include cortex-m to, say, mask interrupts or call one of the assembly intrinsics (like a HAL, or RTIC), would have to decide if it was going to support cortex-m 0.7 or cortex-m 0.8, because it could not do both (at least not without messy feature flags). Everyone would need to put out a breaking change release, switching over from 0.7 to 0.8, and the long tail on those ripples would reach out far into the future. Until fully resolved, the ecosystem would be split.

One step forward is to stop having the PACs depend on cortex-m and instead have them depend on a much smaller crate called cortex-m-types - one that only defines the traits and types that PACs need. The PACs and cortex-m then only have to agree on which version of that types crate to use, and it is then easier to make breaking changes to cortex-m because it only requires the HAL and the application to agree on the version (and some HALs don't use cortex-m at all), rather than having the HAL, the PAC and the Application all agree.

Oh right, I also forgot the critical-section-single-core impl I mentioned above, which uses no_mangle functions, which is another reason why you cannot have two versions of cortex-m in the same tree (at least not two that both implemnent that feature). But having sat down and thought about it for 20 minutes, I now remember that it's not the main issue.

So, if we put out a breaking change release of cortex-m, there would be some PACs still using cortex-m 0.7 and anyone using those PACs would have to use cortex-m 0.7, whilst other PACs might be using cortex-m 0.8 and anyone use one of those PACs would have to use cortex-m 0.8. Any library crate that wanted to include cortex-m to, say, mask interrupts or call one of the assembly intrinsics (like a HAL, or RTIC), would have to decide if it was going to support cortex-m 0.7 or cortex-m 0.8, because it could not do both (at least not without messy feature flags). Everyone would need to put out a breaking change release, switching over from 0.7 to 0.8, and the long tail on those ripples would reach out far into the future. Until fully resolved, the ecosystem would be split.

Perhaps I am missing some important nuance, but couldn't PAC-s and other libraries depend on a version range of >=0.7.3, <0.9. Provided these downstream libraries are not affected by any of the breaking changes in 0.8 there should be no issue. (Looking at the list of breaking changes from #183 (comment), it seems to me that 95% of libraries should not be affected by these changes and could use 0.7.3 and 0.8 interchangably.)

They could but they donโ€™t. We (the WG) do not own the PACs and co-ordinating such an update across the ecosystem would be hugely expensive in terms of effort, and unlikely to be 100% successful.

Sure, but you said that any library had to choose between supporting 0.7 and 0.8 because they could not support both and any library updating to 0.8 would have to put out a breaking change and it seems to me that both of these issues can be avoided for most libraries by using a version range to support 0.7 and 0.8 at the same time.

No, I said:

would have to decide if it was going to support cortex-m 0.7 or cortex-m 0.8, because it could not do both (at least not without messy feature flags)

If a library uses a version range to allow for both, should it expect the old API from 0.7 or the new API from 0.8? I hand waved over this as "messy feature flags".

Isn't most of the API the same for 0.7 and 0.8? AFAIK there are only a handful of breaking changes in 0.8 and half of them are removals of already deprecated stuff. I don't think most libraries would need to care which API they are using.

Yeah, maybe? That doesn't change our position on putting out breaking releases of the cortex-m crate.