Skip to content

Conversation

@xudongzheng
Copy link
Contributor

Use get_rand_64() from Pico SDK for entropy.

This is somewhat based on #66764.

@xudongzheng xudongzheng force-pushed the rp2350-entropy-pr branch 2 times, most recently from df8de81 to be3cfa0 Compare December 24, 2024 03:59
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this cast ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I took that part from an earlier version of another entropy driver. The cast has been removed.

Copy link
Contributor

@tomi-font tomi-font left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any answer to @yonsch's comment in your previous PR #66764 (comment)?

@xudongzheng
Copy link
Contributor Author

xudongzheng commented Dec 30, 2024

Do you have any answer to @yonsch's comment in your previous PR #66764 (comment)?

@yonsch is referring to the fact that RP2040 lacks a hardware random number generator so it uses other sources as seed.

RP2350 has a hardware random number generator and uses that in pico-sdk: https://github.com/raspberrypi/pico-sdk/blob/95ea6acad131124694cda1c162c52cd30e0aece0/src/rp2_common/pico_rand/rand.c#L121

@xudongzheng xudongzheng force-pushed the rp2350-entropy-pr branch 2 times, most recently from 338dfec to f069b11 Compare December 30, 2024 15:49
Copy link
Contributor

@ajf58 ajf58 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a few things need addressing here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be wrapped in a Zephyr spinlock. There would be a slight performance hit because of the Zephyr spinlock + Pico SDK's hardware-based spin_lock (and we're holding a k_spinlock for longer than strictly required), but this would ensure that users get the Zephyr-provided guarantees about spinlocks.

nit: word has overloaded meaning, I'd avoid this variable name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable renamed to value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs thinking about, in particular, how this interacts, by default, with Pico SDK's alarm pool. I think PICO_TIME_DEFAULT_ALARM_POOL_DISABLED will need to be set, at least.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the earlier PR #66764, PICO_TIME_DEFAULT_ALARM_POOL_DISABLED=1 was needed due to building ${common_dir}/pico_time/time.c. However PICO_TIME_DEFAULT_ALARM_POOL_DISABLED doesn't seem to be referenced in either of the two C files added in this PR:

  • ${rp2_common_dir}/hardware_timer/timer.c
  • ${rp2_common_dir}/pico_rand/rand.c

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initialise_rand -> capture_additional_rosc_samples -> sleep_until -> add_alarm_at -> alarm_pool_add_alarm_at, and so on, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem like PICO_RAND_SEED_ENTROPY_SRC_ROSC or PICO_RAND_ENTROPY_SRC_ROSC are defined so capture_additional_rosc_samples() shouldn't be called.

Function alarm_pool_add_alarm_at() is defined in src/common/pico_time/time.c and that doesn't seem to be added from anywhere in Zephyr.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks for taking the time to walk through the code path here.

@xudongzheng xudongzheng force-pushed the rp2350-entropy-pr branch 2 times, most recently from 1edd3e0 to 14d6fb1 Compare January 17, 2025 21:41
Copy link
Contributor

@ajf58 ajf58 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think my concern about the alarm pool has been addressed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
uint64_t value = get_rand_64();
K_SPINLOCK(&entropy_lock) {
uint64_t value = get_rand_64();
}

Only the call to get_rand_64() needs wrapping in the spinlock. Reducing the amount of code in the lock is preferable, and use the helper macro to limit the scope of the key.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've wrapped get_rand_64() with the K_SPINLOCK() macro.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initialise_rand -> capture_additional_rosc_samples -> sleep_until -> add_alarm_at -> alarm_pool_add_alarm_at, and so on, no?

@xudongzheng
Copy link
Contributor Author

PR rebased on top of 03fa6a0 to address merge conflicts.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 3rd arg of memcpy is size_t.

And for now, we mostly follow the old habit of "declaring variables at the top of a block", so please do so if possible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, to_copy should be size_t.

I'm putting a thumbs-down against "declaring variables at the top of a block"
a) Reviewers should not introduce ad-hoc coding styles.
b) It's another throwback to ancient C standards (i.e. C90, which is 4 versions and 30 years too old). Mixing declarations and code is a Good Thing: by reducing a variables scope/lifetime it makes it easier to understand when/where a variable is used. In contrast, sticking all the variable declarations together makes it harder to do this. Some people incorrectly believe they can estimate stack usage by counting number/size of variables declared, and this tacitly encourages such behaviour.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In reality, this habit is still strong
and is frequently pointed out in reviews. #83358 (comment)
Since there is no clear affirmative or negative provision in the terms and conditions, it is up to the discretion of the reviewer or maintainer.
I think that, currently, most cases lean towards this "old habit."

As far as I'm concerned, this habit was abolished in the 2012 MISRA-C regulations,
so I don't intend to block it, but I would probably start by saying, "Do it the way everyone else does."
Even this would probably be a relatively radical stance among maintainers.

Copy link
Contributor

@ajf58 ajf58 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot I like about this implementation (it's very well laid out, order of #include s is neat, DTS file changes are nicely in order).

A couple of things need tweaking.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
depends on DT_HAS_RASPBERRYPI_PICO_RNG_ENABLED
depends on DT_HAS_RASPBERRYPI_PICO_RNG_ENABLED
depends on SOC_SERIES_RP2350

Given that *rpi_pico*.c is often used for both RP2040 and RP2350 series SoCs, perhaps the additional constraint will avoid people trying to use this entropy generator on the RP2040, where it would be unsuitable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added per suggestion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At build-time this is introducing a warning:

zephyr/build/rpi_pico2/rp2350a/m33/hello_world/zephyr/zephyr.dts:408.12-411.5:
  Warning (simple_bus_reg): /soc/rng: missing or empty reg/ranges property

which this needs looking at.

Ordering should be the other way around (status comes last).

I think the Zephyr convention is meant to be that we don't enable too much stuff by default, with an implicit rationale that we don't want build "hello world" to compile hundreds of files, as that gives a daunting/bad user experience ("I just want to blink and LED, why does that need 130 source files!" kind of response) so this should be disabled by default.

Copy link
Contributor Author

@xudongzheng xudongzheng Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added reg = <0x400f0000 DT_SIZE_K(4)> since that corresponds to TRNG_BASE.

I've moved status to the last line to match other entries in the .dtsi file.

I've disabled &rng by default and enabled it from the board since non-wireless microcontrollers seem to follow this pattern.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unclear where this should be (SoC's dtsi vs board's) as the Zephyr codebase is inconsistent. My gut feeling is (in descending order)

  • Neither; the board doesn't need it to run correctly
  • In the board file
  • Here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is practice in esp32 and nxp, so this is fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The majority of uses of zephyr,entropy are in the SOC definitions, so I think this is the right place.

@tomi-font
Copy link
Contributor

If I remember correctly, you can't reopen the branch you're pushing if the head of the branch you're pushing to has been changed since it was closed. Changing the head of the branch to a0c870d and push, and try reopen again.

Exactly this.

@xudongzheng
Copy link
Contributor Author

The branch is back at a0c870d, though I don't see a button to reopen the pull request. Perhaps someone with the right permissions can do it now?

@soburi soburi reopened this Jun 4, 2025
@github-actions github-actions bot removed the Stale label Jun 5, 2025
@xudongzheng xudongzheng marked this pull request as draft June 6, 2025 04:33
@sonarqubecloud
Copy link

sonarqubecloud bot commented Jun 6, 2025

@github-actions
Copy link

github-actions bot commented Aug 6, 2025

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@sonarqubecloud
Copy link

@xudongzheng xudongzheng marked this pull request as ready for review August 15, 2025 21:15
@xudongzheng
Copy link
Contributor Author

Previously CI was failing on the following test:

west build -p -b rpi_pico2/rp2350a/m33 tests/crypto/mbedtls -T crypto.mbedtls

This should be addressed in the latest push with a __CONCAT definition in modules/hal_rpi_pico/pico/config_autogen.h.

@github-actions github-actions bot removed the Stale label Aug 16, 2025
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this required? Maybe SDK functions using this could be avoided?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pico SDK mixes the TRNG output with uninitialized memory: https://github.com/raspberrypi/pico-sdk/blob/a1438dff1d38bd9c65dbd693f0e5db4b9ae91779/src/rp2_common/pico_rand/rand.c#L365-L374

To work around that, one would have to use capture_additional_trng_samples(), but that's not public API.

size_t to_copy = MIN(sizeof(value), len);

K_SPINLOCK(&entropy_lock) {
value = get_rand_64();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it idiomatic for an entropy source to actually provide more entropy than it has? It only has a boot-time true random value, while this function is fueled by xoroshiro128 algorithm: https://github.com/raspberrypi/pico-sdk/blob/a1438dff1d38bd9c65dbd693f0e5db4b9ae91779/src/host/pico_rand/rand.c

This is a question to subsys maintainers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at https://github.com/raspberrypi/pico-sdk/blob/a1438dff1d38bd9c65dbd693f0e5db4b9ae91779/src/rp2_common/pico_rand/rand.c#L350-L354, each get_rand_64() invocation calls capture_additional_trng_samples() for additional entropy.

The end result is fed into xoroshiro128 as you mentioned.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, not sure if that matches subsystem expectations, but that sounds good. Please keep this thread open

@github-actions
Copy link

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@stef
Copy link

stef commented Oct 27, 2025

hey there, i applied this as a patch to my zephyr ws, and am building it correctly and am using it successfully. am looking forward to not having to patch but seeing this merged. kudos to all involved!

Use get_rand_64() from Pico SDK for entropy.

Signed-off-by: Xudong Zheng <[email protected]>
@sonarqubecloud
Copy link

@stef
Copy link

stef commented Oct 31, 2025

@xudongzheng
Copy link
Contributor Author

@xudongzheng how is this mostly sram0 stuff in this diff https://github.com/zephyrproject-rtos/zephyr/compare/29e0630267bd920a5d1087a1aec14f22319487b9..d42a9052d8940c5c5d50dc9964c7397cd1846f80 related to the rng?

@stef Most of that is not part of the PR and just a result of the rebase. A lot of the RP2350 tests were failing in the previous push and I suspected #98363 was necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants