<re_irc> <@t​imbod7:m​atrix.org> I've switched from blue pills (STM32F1xx) to black pills (STM32F401) and am struggling with the tooling setup via an generic stlink-2 dongle. `cargo embed` successfully builds and starts my code on the F401, but once the new code starts, I lose all ability to communicate with the target device: `cargo embed`...
<re_irc> ... doesn't subsequently work, and nor does `st-info --probe`. v The only way I've managed to recover the situation is to connect an old STM32F4 discovery board as the programmer and wireits working NRST output to the target black pill board. Then `st-flash erase` succeeds, and I'm back with a working stlink again.
<re_irc> <@t​imbod7:m​atrix.org> Any tips as to what might be going on here?
<re_irc> <@d​khayes117:m​atrix.org> TIL That `to_be_bytes()` the `be` stands for big endian not the word be. For little endian, use `to_le_bytes()` LOL.
<re_irc> <@a​damgreig:m​atrix.org> timbod7: common culprits are the use of the WFI or WFE instruction or other low-power mode that causes the core to go to sleep without also enabling debug-during-sleep, or changing the GPIO pins for debug to some other mode (e.g. by using gpioa.moder.write() without specifying PA13/PA14 shold be AF0)
<re_irc> <@a​damgreig:m​atrix.org> if you're using RTIC, its default idle will also go to sleep
<re_irc> <@a​damgreig:m​atrix.org> dkhayes117: I guess little endian should be `not_to_be_bytes()` :P
<re_irc> <@t​imbod7:m​atrix.org> > common culprits are the use of the WFI
<re_irc> <@t​imbod7:m​atrix.org> That's it. I would had saved a lot of time by asking yesterday. adamgreig Thanks!!!!
<re_irc> <@a​damgreig:m​atrix.org> when you enter a sleep mode the debugger is turned off by default to save power, but you can write to the DBGMCU bits DBG_SLEEP, DBG_STOP, and DBG_STANDBY to keep it enabled
<re_irc> <@a​damgreig:m​atrix.org> (so power consumption is higher, don't leave them set when actually releasing battery-powered devices, but handy for debugging and so on)
<re_irc> <@a​damgreig:m​atrix.org> (but you can also just not use WFI/WFE and like, run a nop loop or something, if you don't especially care about power)
<re_irc> <@t​halesfragoso:m​atrix.org> adamgreig: Sometimes you also need to enable a bus master, like DMA
<re_irc> <@t​imbod7:m​atrix.org> 👍️ It took me a long time to recover from this scenario. I guessed that I needed a well timed NRST input to recover, but I had to learn that the RST pin on a generic stlink dongle is something different, and dug up an old discovery board with a working NRST output.
<re_irc> <@a​damgreig:m​atrix.org> in principle a debugger can drive nRST, attach to the chip, tell it to halt on start, then release nRST and begin debugging; probe-rs stuff usually has like --connect-under-reset or whatever
<re_irc> <@a​damgreig:m​atrix.org> but yea, your probe needs to do it and conceivably lots of generic stlinks don't
tokomak has joined #rust-embedded
tokomak_ has joined #rust-embedded
tokomak has quit [Ping timeout: 272 seconds]
fabic has joined #rust-embedded
sys64738 has joined #rust-embedded
<re_irc> <@s​ys64738:c​ybre.space> hi there, im trying to play around with https://github.com/alvinhochun/gd32vf103-pinecil-demo-rs/ , and, compiling & flashing with dfu & running seems to be working fine, but i dont want to wear out the flash too much so running from ram (using eg. openocd `load_image`) would be nice. thig is, for that a...
<re_irc> ... different linker script would be needed i think (so that it runs at the address it thinks it is running), but cant see anything relevant like a linker script in the gd32vf103 pac and hal crates (which is where id expect these to be, is that right?). is there any way to change this behavior? this is my first rust project so im not too...
<re_irc> ... familiar with the compiler/linking part of the tooling (also is this the right place to ask?)
<re_irc> <@a​damgreig:m​atrix.org> the relevant part of the linker script is https://github.com/alvinhochun/gd32vf103-pinecil-demo-rs/blob/master/memory.x
<re_irc> <@a​damgreig:m​atrix.org> the gd32vf103 has 100_000 write cycles _minimum_ on the flash though, you probably won't wear it out
<re_irc> <@s​ys64738:c​ybre.space> .... oh
<re_irc> <@s​ys64738:c​ybre.space> ..... oh why did i *not* notice that earlier
<re_irc> <@s​ys64738:c​ybre.space> but thanks!
<re_irc> <@a​damgreig:m​atrix.org> the rest of the linker script comes from https://github.com/rust-embedded/riscv-rt/blob/master/link.x
<re_irc> <@s​ys64738:c​ybre.space> ah thanks
<re_irc> <@a​damgreig:m​atrix.org> you can see both getting included here: https://github.com/alvinhochun/gd32vf103-pinecil-demo-rs/blob/master/.cargo/config#L3-L4
<re_irc> <@a​damgreig:m​atrix.org> the idea being the application defines just the relevant memory addresses and sizes in its memory.x, and the riscv-rt script (which handles the reset and initialising memory to 0/flash values) provides a default full linker script that uses those memory sections from memory.x
<re_irc> <@s​ys64738:c​ybre.space> ah i see, thanks
<re_irc> <@s​ys64738:c​ybre.space> anyway i got it working now, with openocd loading the binary into ram, so i think i can continue on my own now, thanks again
emerent has quit [Ping timeout: 258 seconds]
emerent has joined #rust-embedded
<re_irc> <@h​enrik_alser:m​atrix.org> adamgreig: Never realized Hamlet was referring to a coding problem
fabic has quit [Ping timeout: 250 seconds]
neceve has joined #rust-embedded
<re_irc> <@s​tu_:m​atrix.org> therealprof: Small status update!
<re_irc> <@s​tu_:m​atrix.org> You can follow the progress of our `cortex-a` crate [here](https://github.com/vbe0201/Saturnus/tree/main/crates/cortex-a/src).
<re_irc> <@s​tu_:m​atrix.org> Right now I'm just trying to get the same content as the `rust-embedded/cortex-a` crate, but we are already working on a good API for controlling the MMU
neceve has quit [Ping timeout: 245 seconds]
neceve has joined #rust-embedded
sys64738 has left #rust-embedded [WeeChat 3.2]
fabic has joined #rust-embedded
neceve has quit [Read error: Connection reset by peer]
fabic has quit [Ping timeout: 250 seconds]
SanchayanMaity has joined #rust-embedded
dreamcat4 has joined #rust-embedded
GenTooMan has quit [Ping timeout: 272 seconds]
GenTooMan has joined #rust-embedded
<re_irc> <@d​khayes117:m​atrix.org> struct my_struct {
<re_irc> <@d​khayes117:m​atrix.org> I have a struct that I'd like to hold an array of structs.
<re_irc> <@d​khayes117:m​atrix.org> struct_array: [other_struct;4],
<re_irc> <@d​khayes117:m​atrix.org> I've been racking my brain about how to create a new instance `my_struct` with a for loop. IE take a u32, break into bytes, turn into struct_arrays and return `my_struct`. Is there a better, more idiomatic way of doing something like this?
<re_irc> <@d​khayes117:m​atrix.org> }
<re_irc> <@d​khayes117:m​atrix.org> The `other_structs` takes the bytes and turns into high level information and not just raw bits.
<re_irc> <@d​irbaio:m​atrix.org> the easy way is to create a `my_struct` with dummy `other_struct`s, then overwrite them
<re_irc> <@d​irbaio:m​atrix.org> the compiler will probably optimize it
<re_irc> <@d​irbaio:m​atrix.org> depending on what `other_struct` is, maybe it's not possible to create a "dummy" instance of it
<re_irc> <@d​irbaio:m​atrix.org> then, you have to do it the hard way, with MaybeUninit+unsafe
<re_irc> <@d​khayes117:m​atrix.org> I was afraid of that. Hoped for something cleaner. Back to the drawing board I guess.
<re_irc> <@d​khayes117:m​atrix.org> I guess I could just hold the raw bytes in the structs, and if you want the high level description of that byte call a method.
<re_irc> <@h​enrik_alser:m​atrix.org> dkhayes117: If you use it a lot it may make senase to impl `FromIterator` for your struct
<re_irc> <@h​enrik_alser:m​atrix.org> And if you can `#[derive(Default)]` for your structs it might not be too messy
<re_irc> <@d​khayes117:m​atrix.org> henrik_alser: I hadn't thought of that, but yeah I could
<re_irc> <@t​heunkn0wn1:m​atrix.org> wouldn't the idomatic way of de/serializing binary data be via Serde and a serialization layer like `cbor` or `postcard`?
<re_irc> <@t​heunkn0wn1:m​atrix.org> that does assume you have control of the serialization
<re_irc> <@d​khayes117:m​atrix.org> The u32 data are from registers that are densely packed configuration of 8bits. IE each byte is a configuration for memory protection. There are currently a max of 4 registers. I haven't used postcard, but isn't that more for comms stuff?
<re_irc> <@t​heunkn0wn1:m​atrix.org> Ah, yes I had presumed you were doing coms stuff as that is where my mind currently is.
<re_irc> <@t​heunkn0wn1:m​atrix.org> Methinks for reading packed integers bitfields can be used, though those are a mess of proc-macros last i made use of them.
<re_irc> <@t​heunkn0wn1:m​atrix.org> I think there are some packages that make generating register wrappers easier, can't recall their names off the top of my head.
<re_irc> <@g​rantm11235:m​atrix.org> dkhayes117: You can fill a `heapless::Vec<other_struct, 4>` and then turn it into a `[other_struct; 4]` https://docs.rs/heapless/0.7.4/heapless/struct.Vec.html#method.into_array
<re_irc> <@g​rantm11235:m​atrix.org> That does all of the unsafe MaybeUninit stuff for you behind the scenes
<re_irc> <@d​khayes117:m​atrix.org> I thought about heapless, but this is for the `riscv` architecture support crate and I think the extra dependency isn't the best option. We have low level control by simply reading/writing usize to the reg. I'm adding some APIs to make the configurations more readable.
<re_irc> <@d​khayes117:m​atrix.org> pub mod pmpcfg0 {
<re_irc> <@d​khayes117:m​atrix.org> use super::Pmpcsr;
<re_irc> <@d​khayes117:m​atrix.org> use bit_field::BitField;
<re_irc> <@d​khayes117:m​atrix.org> I thought instead of converting only one byte of the entire register, why not take the entire register and returning an array of Pmp config structs.
<re_irc> <@t​heunkn0wn1:m​atrix.org> thislooks promising and similar to the API I see in HAL crates
<re_irc> <@t​heunkn0wn1:m​atrix.org> https://crates.io/crates/register
<re_irc> <@d​irbaio:m​atrix.org> it's usually easier to have a struct wrapping the u32 and provide methods to get/set the fields
<re_irc> <@d​irbaio:m​atrix.org> this is what svd2rust-generated code and cortex-m do
<re_irc> <@d​khayes117:m​atrix.org> dirbaio: So use like a closure type setup? Already am reading into a struct like so
<re_irc> <@d​khayes117:m​atrix.org> pub struct Pmpcsr {
<re_irc> <@d​khayes117:m​atrix.org> /// Holds the raw contents of the PMP CSR
<re_irc> <@d​khayes117:m​atrix.org> bits: usize
<re_irc> <@d​khayes117:m​atrix.org> }
<re_irc> <@d​irbaio:m​atrix.org> not necessarily a closure, you can have `.foo()` and `.set_foo()` methods
<re_irc> <@d​khayes117:m​atrix.org> How do you keep the struct in sink with the register value. Do you destroy the struct after a `set`, or just update the contents? Which gets into only allowing a single instance of Pmpcsr. I want to keep the low level direct write of a usize for more efficient context switches when necessary, but this could...
<re_irc> ... invalidate the Pmpcsr if it already exists.
<re_irc> <@t​heunkn0wn1:m​atrix.org> completely unrelated,
<re_irc> <@t​heunkn0wn1:m​atrix.org> ```rs
<re_irc> <@t​heunkn0wn1:m​atrix.org> // Split the resulting buffer into word-sized chunks
<re_irc> <@t​heunkn0wn1:m​atrix.org> let buffer = &buffer[0..total_words * 4];
<re_irc> <@g​rantm11235:m​atrix.org> Instead of reading as a usize, doing bit fiddling, and writing a usize, you would read as a `Pmpcsr`, call `set_index` on that struct, and then write it back
<re_irc> <@d​khayes117:m​atrix.org> GrantM11235: If you do a usize write though, you can set all 4, or 8 for RV64, configs at once. With the `set` methods, you would need to specify a byte index to apply it too.
<re_irc> <@d​khayes117:m​atrix.org> the usize write does offer an avenue for errors though because the binary bits are harder to read
<re_irc> <@g​rantm11235:m​atrix.org> The `Pmpcsr` struct isn't the actual register, it is just a working copy of it. You can modify it as much as you want before you write it back
<re_irc> <@d​khayes117:m​atrix.org> So would you get rid of a usize write all together?
<re_irc> <@g​rantm11235:m​atrix.org> Yes
<re_irc> <@g​rantm11235:m​atrix.org> This way is much more readable and it should be just a efficient
tokomak_ has quit [Ping timeout: 250 seconds]
<re_irc> <@d​khayes117:m​atrix.org> I guess you could chain several `set` methods together, then have a `write_reg()`, or `apply()` method to write to the register once all the configuration is done?
<re_irc> <@g​rantm11235:m​atrix.org> You could do that, or you could do what `svd2rust` does and use closure based methods
<re_irc> <@j​amesmunns:m​atrix.org> I guess it depends on what you want to do if the `try_into` method fails
<re_irc> <@j​amesmunns:m​atrix.org> Here, I just discard it (you should probably check you get `total_words` back
<re_irc> <@t​heunkn0wn1:m​atrix.org> jamesmunns: that method should never fail i think, since the chunks are always of the right size.
<re_irc> <@g​rantm11235:m​atrix.org> jamesmunns: That try_into should never fail
<re_irc> <@j​amesmunns:m​atrix.org> Yeah
<re_irc> <@t​heunkn0wn1:m​atrix.org> i would use `into()` but Rust says no.
<re_irc> <@d​khayes117:m​atrix.org> GrantM11235: Thanks for the advice. I'll mull over some more.
<re_irc> <@j​amesmunns:m​atrix.org> Yeah, I think there is some unstable method that gives you back actual arrays?
<re_irc> <@j​amesmunns:m​atrix.org> but I can't remember
<re_irc> <@t​heunkn0wn1:m​atrix.org> jamesmunns: Im trying to minimize my usage of unstable and unsafe code.\
<re_irc> <@j​amesmunns:m​atrix.org> Yeah, honestly I'm not sure if you can make it much cleaner.
<re_irc> <@j​amesmunns:m​atrix.org> anything more complex than that, and I'd probably say you want something like the `scroll` crate: docs.rs/scroll
<re_irc> <@g​rantm11235:m​atrix.org> dkhayes117: The closure-based api is convenient because it does the reading and the writing for you, you just do the modifying with the closure
<re_irc> <@t​heunkn0wn1:m​atrix.org> the only think i can think of is figuring out if i can use DMA against this peripheral, but that would only make this project even more complicated :|
<re_irc> <@t​heunkn0wn1:m​atrix.org> in case of an X/Y: i have to remap an `[u8]` that is aligned to 4 bytes to a `[u32]` (BE), which i can then feed to the CRC peripheral; i cannot feed the `[u8]` directly because it produces garbage output
<re_irc> <@g​rantm11235:m​atrix.org> jamesmunns: https://doc.rust-lang.org/std/slice/struct.ArrayChunks.html
<re_irc> <@a​damgreig:m​atrix.org> it's a shame core doesn't have a method that turns an iter of u8 to an iter of u32, that would be nice
<re_irc> <@t​heunkn0wn1:m​atrix.org> that would be real nice.
<re_irc> <@a​damgreig:m​atrix.org> I think the byteorder crate might have something like that
<re_irc> <@j​amesmunns:m​atrix.org> GrantM11235: That's the one!
<re_irc> <@a​damgreig:m​atrix.org> and you could always check alignment and do an unsafe slice::from_raw_parts
<re_irc> <@j​amesmunns:m​atrix.org> I mean, the only thing that could fail would be alignment problems
<re_irc> <@j​amesmunns:m​atrix.org> yeah
<re_irc> <@t​heunkn0wn1:m​atrix.org> this entire bit of code is because of alignment issues; this is the only way I have found to reproduce the device's CRC value
<re_irc> <@a​damgreig:m​atrix.org> no alignment issues with arraychunks or a hypothetical iterator adaptor, though could be more efficient if aligned
<re_irc> <@a​damgreig:m​atrix.org> computing crcs sure is an art, lol
<re_irc> <@a​damgreig:m​atrix.org> which device?
<re_irc> <@t​heunkn0wn1:m​atrix.org> adamgreig: stm32f446RETx
<re_irc> <@a​damgreig:m​atrix.org> you can almost certainly compute the crc byte-at-a-time but maybe not worth it
<re_irc> <@t​heunkn0wn1:m​atrix.org> no, this peripheral only works on u32s.
<re_irc> <@a​damgreig:m​atrix.org> oh, right, I thought you were trying to replicate its effect in software
<re_irc> <@t​heunkn0wn1:m​atrix.org> and the HAL's method that accepts a u8 emits an unreproducable CRC due to byeorder.
<re_irc> <@a​damgreig:m​atrix.org> ah, yea, that's annoying
<re_irc> <@t​heunkn0wn1:m​atrix.org> I need to be able to calculate the same CRC on my host, which isn't using hardware CRC.
<re_irc> <@t​heunkn0wn1:m​atrix.org> or, rather, isn't using the same assumptions the stm32f4xx-hal made.
<re_irc> <@a​damgreig:m​atrix.org> what you have for getting u32 from the u8 is fine bt if you know the u8 is aligned you can definitely save cpu time by doing an unsafe from_raw_parts to get u32s to feed the crc, or you could use dma too
<re_irc> <@d​khayes117:m​atrix.org> GrantM11235: Where can I find an example of the closure-based api
<re_irc> <@a​damgreig:m​atrix.org> and just point the dma at the first u8 and tell it it's u32...
<re_irc> <@a​damgreig:m​atrix.org> but I think what you've got now is probably fine until you're hitting performance problems with it, and it's pretty clear rust
<re_irc> <@t​heunkn0wn1:m​atrix.org> hrm, that would require breaking up both my TX and RX methods into at least two parts and figuring out which one was computing the CRC :
<re_irc> <@j​amesmunns:m​atrix.org> `buffer.as_ptr().cast::<u32>()`
<re_irc> <@a​damgreig:m​atrix.org> :o
<re_irc> <@j​amesmunns:m​atrix.org> look, no unsafe!
<re_irc> <@a​damgreig:m​atrix.org> now you have a *const [u32] though right?
<re_irc> <@a​damgreig:m​atrix.org> or just *const u32 I guess
<re_irc> <@j​amesmunns:m​atrix.org> `*const u32`
<re_irc> <@g​rantm11235:m​atrix.org> dkhayes117: https://docs.rs/svd2rust/0.19.0/svd2rust/#read--modify--write-api
<re_irc> <@a​damgreig:m​atrix.org> no unsafe until you actually want to use it :P
<re_irc> <@j​amesmunns:m​atrix.org> if you hand it to a pac register, that's not unsafe either!
<re_irc> <@j​amesmunns:m​atrix.org> well, it is
<re_irc> <@j​amesmunns:m​atrix.org> but like, you might not need the unsafe keyword!
<re_irc> <@a​damgreig:m​atrix.org> you had better
<re_irc> <@a​damgreig:m​atrix.org> all the DMA registers need unsafe to write in stm32-rs at least
<re_irc> <@a​damgreig:m​atrix.org> DMA address registers*