PyroPeter has quit [*.net *.split]
re_irc has quit [*.net *.split]
unmanbearpig has quit [*.net *.split]
Darius has quit [*.net *.split]
richardeoin has quit [*.net *.split]
re_irc has joined #rust-embedded
PyroPeter has joined #rust-embedded
PyroPeter has quit [Changing host]
PyroPeter has joined #rust-embedded
unmanbearpig has joined #rust-embedded
Darius has joined #rust-embedded
richardeoin has joined #rust-embedded
<re_irc> <> Aren't you using volatile to write the static mut address to the DMA register ?
<re_irc> <> Yes, wrapped by the PAC:
<re_irc> <> ```rust
<re_irc> <> .m0ar
<re_irc> <> .write(|w| unsafe { w.bits(mem_addr) });
<re_irc> <>[channel as usize]
<re_irc> <> I don't really understand what's going on, ie why the `defmt` line is keeping the code working. Bizarre on the surface, but I'm sure there's a logical explanation
<re_irc> <> Probably timing, taking the address of the static mut and using it on a volatile operation should be enough t o prevent the compiler from optimizing it out
<re_irc> <> Be sure to use the right fences in the right places, have you read the DMA section of the embeddonomicom ?
<re_irc> <> It can optimize other operations though
<re_irc> <> if mem_addr is an integer already it would not have provenance, maybe the compiler has no way of inferring that the buffer is used?
<re_irc> <> But the integer comes from the address, so the compiler needs to take the address of it
<re_irc> <> If it's optimizing it out, then it wouldn't have an address to start with
<re_irc> <> I also think that integers might have provenance, no ?
<re_irc> <> I.e. you can cast a pointer to an integer and back
<re_irc> <> yeah it's probably fine. would really need to see the code to see if firefrommoonlight is doing something tricky to get the address.
<re_irc> <> You can, but my understanding is that when you cast back to pointer the new pointer does not have the same provenance as the old.
<re_irc> <> Ralf Jung's article is my goto for this, it's the clearest explanation I've found.
<re_irc> <> I have read it, but could use another go through!
<re_irc> <> The `mem_addr` is passed as `buf.as_ptr() as u32`
<re_irc> <> Reading that article
<re_irc> <> Where buf is a `static mut` u32
<re_irc> <> it would confirm if OUT_BUF had been optimised away. I *think* ffm was suggesting that the accesses, not the variable, were optimised out.
<re_irc> <> not sure what buf.as_ptr() would yield if that happened - it would definitely be weird though
<re_irc> <> 9names: Yeah, I already read it some time ago, I was thinking more about pointer escapes, which is also pretty underspecified
starblue has quit [Ping timeout: 260 seconds]
starblue has joined #rust-embedded
<re_irc> <> And yeah I was confusing myself with the whole provenance thing, but hard to see how it plays with pointer escapes
<re_irc> <> tbh I don't have a good grasp on how pointers work
<re_irc> <> despite using them all over on this project for DMA reads and writes
<re_irc> <> I dont think it's a provenance problem, probably something way simpler
<re_irc> <> I suppose a next step is experimenting to see what causes it to work and not, eg moving the print, replacing it with other things etc
<re_irc> <> Make sure you're correctly waiting for the DMA to finish
<re_irc> <> Probably not relevant, but this is a quadrupled buffer, sort of. It's a double buffer to sequence reads and writes, and each side is interleaved with 2 audio channels
<re_irc> <> It's circular
<re_irc> <> And the writes are triggered by half and full transfer complete ISRs; I *think* this ensures it only writes when ready
<re_irc> <> Ie, on full TC, I write to the second half of the buffer (since it's about to start playing from the first), and vice versa for half TC
<re_irc> <> So you aren't using the buffer at all on your rust code ?
<re_irc> <> I am
<re_irc> <> I.e. reading/writing to it
<re_irc> <> I mean you, not the DMA
<re_irc> <> The writes are triggered by those ISRs
<re_irc> <> Correct
<re_irc> <> The DMA is a set-and-forget
<re_irc> <> (For this part of the program)
<re_irc> <> Isn't one DMA doing the write and other doing reads ?
<re_irc> <> *I should clarify. This is the case for a realtime audio part of the program
<re_irc> <> The part that's triggering this odd behavior is output only
<re_irc> <> So just a DMA SAI buffer
<re_irc> <> If you don't touch the buffer then this is hardly a (mis)compilation problem
<re_irc> <> I do touch the buffer
<re_irc> <> For what ?
<re_irc> <> I send it to DMA once, then do a write each time half is passed to the audio periph
<re_irc> <> Updating the content
<re_irc> <> With tones, static etc for an audiogram
<re_irc> <> Didnt you say that the DMA does both write and read ?
<re_irc> <> For *this* part of the program, I write values to the DMA buffer based on what tones etc to play, and this is passed to the SAI periph to play sounds
<re_irc> <> Who writes the values, you or the DMA ?
Foxyloxy has quit [Quit: Textual IRC Client:]
<re_irc> <> I do
<re_irc> <> I'm transfering data to a peripheral
<re_irc> <> Mem to periph
<re_irc> <> Sure, but you could do that completely with DMA, i.e. one DMA to memory and one DMA from memory
<re_irc> <> Which I thought you did with your explanation from before
<re_irc> <> No need for DMA to memory here
<re_irc> <> I do the bi-directional thing for a different part of the program
<re_irc> <> So make sure to finish touching the buffers before the DMA wraps around
<re_irc> <> That is very complicated to do safely
<re_irc> <> Good point - I don't have a way to guarantee that
<re_irc> <> (Although I'm suspicious it completes much faster than the DMA write takes... I need to verify it)
<re_irc> <> That's a problem I'll need to solve eventually
<re_irc> <> Also use compiler fences before passing the address to the DMA and one compiler fence every time before touching the buffer
<re_irc> <> Basically, for this to be *safe*, the write has to complete faster than the other half of the buffer unloads, or weird stuff will happen
<re_irc> <> Nice - will add that now. Don't have a good feel for when to use them
<re_irc> <> DMA section of the embeddonomicom :)
<re_irc> <> Still need to re-read that
<re_irc> <> I have some comments in my code from it
<re_irc> <> (HAL-side)
<re_irc> <> I appreciate all the help
<re_irc> <> No problem, good luck
<re_irc> <> I'll modify the code As you said re compiler fences; currently don't have that
starblue has quit [Ping timeout: 246 seconds]
Foxyloxy has joined #rust-embedded
starblue has joined #rust-embedded
fabic has joined #rust-embedded
PyroPeter has quit [Ping timeout: 260 seconds]
PyroPeter has joined #rust-embedded
PyroPeter has quit [Ping timeout: 252 seconds]
PyroPeter has joined #rust-embedded
jackneillll has joined #rust-embedded
jackneilll has quit [Ping timeout: 260 seconds]
fabic has quit [Ping timeout: 264 seconds]
<re_irc> <> Hi, I'm trying to create a new target for probe-rs. I keep getting: `No flash memory contains the entire requested memory range 0x0000c000.. 0xc0c0`. In memory.x I have origin: 0xc000, length = 960K for FLASH(rx). In the target.yml flash I have start: 0 and end: 0xf0000
<re_irc> <> But I have tried to stip away most of the autogenerated stuff to:
<re_irc> <> name: Apollo Series
<re_irc> <> ---
<re_irc> <> manufacturer: ~
<re_irc> <> there is no Nvm region in that snippet
<re_irc> <> Ah, that should match the flash?
<re_irc> <> i'm pretty sure that's required, yes.
<re_irc> <> non-vola mem.. makes sense
<re_irc> <> It is present for every other auto genrated target
<re_irc> <> maybe for loading program into ram..
<re_irc> <> ?
<re_irc> <> yeah, if it matches ram it just copies it into ram, otherwise it tries to find a matching flash algorithm
<re_irc> <> Ok! thanks.. I'll try some more.
<re_irc> <> Well, one step closer.. Pretty sure the original bootloader is gone now, so that's a start
<re_irc> <> ❯ cargo run --example blink -- -v
<re_irc> <> Compiling sparkfun-redboard-artemis v0.1.0 (/home/gauteh/dev/ambiq-rs/boards/sparkfun-redboard-artemis)
<re_irc> <> Finished dev [unoptimized + debuginfo] target(s) in 0.46s
<re_irc> <> Running `probe-run --chip AMAPOLLO3B target/thumbv7em-none-eabihf/debug/examples/blink -v`
tokomak has joined #rust-embedded
_whitelogger has joined #rust-embedded
tokomak has quit [Ping timeout: 245 seconds]
<re_irc> <> I'm just checking out the `embedded-time` crate and need some help. I have an Instant now created from a milliseconds clock. How do I get the raw value?
fabic has joined #rust-embedded
<re_irc> <> Maybe my question is not precise enough. How do I get the number of elapsed milliseconds from the start as an integer? Convert Instant to a Duration? Don't use an Instant at all but a Duration right from the start?
<re_irc> <> Instant::duration_since_epoch probably?
<re_irc> <> embedded-time's Clock has a try_now() that gives you the current Instant, and Instant's duration_since_epoch() gives you a Duration between the clock 0 and that instant, I don't know to go from the Duration to milliseconds, perhaps try_into() for Milliseconds (which impls TryFrom<Generic>)?
<re_irc> <> I already tried `duration_since_epoch()` which gives you some generic result. How do you convert that into a duration?
<re_irc> <> It returns `duration::Generic<Clock::T>`.
<re_irc> <> I'm really asking myself if all this is too complicated or if am just to stupid for it.
<re_irc> <> it's definitely more complicated than having a function that just returns millis since boot
<re_irc> <> it's not entirely clear to me but I think you can create a object from your generic Duration
<re_irc> <> so something like `let ms: Milliseconds<u64> = my_clock.try_now().unwrap().duration_since_epoch().try_into().unwrap()`?
<re_irc> <> Thanks, I try it.
<re_irc> <> No, there's still a problem with try_into().
<re_irc> <> Error message: "the trait `TryFrom<embedded_time::duration::Generic<<Clock as embedded_time::Clock>::T>>` is not implemented for `Milliseconds`"
<re_irc> <> :/ this sure seems like it should be easier...
<re_irc> <> this example seems like it should be similar except you use duration_since_epoch
<re_irc> <> checked_duration_since() returns a Generic<Clock::T>> just like duration_since_epoch
<re_irc> <> So why does the try_into() fail?
<re_irc> <> not sure... hopefully someone who has actually used embedded-time in anger has an idea
<re_irc> <> newam I've been thinking more on integer provenance, if they don't have it, how would `uintptr_t` satisfy the C spec with regards to casting from ptr-int and back to ptr and both ptr compare equal ?
<re_irc> <> Oh, sorry, it was 9names
<re_irc> <> This is all to figure it out if we can escape a ptr by escaping its integer representation. If we can't do that then our DMA implementations will have problems
<re_irc> <> two pointers with different provenance can compare equal in C.
<re_irc> <> uintptr_t only needs to be an integer large enough to hold store a pointer to satisfy the C spec.
<re_irc> <> transforms between pointers and integers are implementation defined, so you're already on your own if you're doing it.
<re_irc> <> or i should say: transform from pointer to integer is defined, but the other way is impl def.
<re_irc> <> 9names: I think the idea of the C spec is to be able to re-use the ptr casted from the integer, no ?
<re_irc> <> But to re-use it you need provenance, no ?
<re_irc> <> if you create a pointer it has provenance (to the thing you say it pointed to). if that thing isn't an object you get UB. if you then do pointer arithmetic and step outside that object you get UB.
<re_irc> <> they also haven't really specified that in the language, hence all the papers and people complaining that compiler writers are ruining their perfectly valid C.
<re_irc> <> 9names: From where does this provenance comes from ?
<re_irc> <> What confuses me, is that if an integer doesn't have provenance, it can't alias with any pointer, right ?
<re_irc> <> Or am I getting it wrong ?
<re_irc> <> As an example:
<re_irc> <> int main() {
<re_irc> <> ```C
<re_irc> <> void f(uintptr_t);
<re_irc> <> Given that integers don't have provenance, can't the compiler optimize the return a to return 0 ?
tokomak has joined #rust-embedded
<re_irc> <> uh... no? that's not even passing a pointer. it's passing an integer representation of the pointer, in whatever size uintptr_t is (which is *at least* as large as ptr)
<re_irc> <> the callee is free to make a pointer out of it - hopefully they choose a valid type (invoking impl defined behaviour), and that pointer will not have the same provenance as a.
<re_irc> <> which means the compiler is not free to assume the new pointer *is* a and optimise either of them using that information.
<re_irc> <> Sorry, not sure if I follow, it the hypothetical new ptr doesn't have the provenance of `a`, how could it modify `a` ?
<re_irc> <> And yes, I'm passing it as an integer on purpose, this is to simulate DMA operations
<re_irc> <> Describing it as an integer helps in this case, I think.
<re_irc> <> I don't think your example would be sufficient to really explain it though. Let me try something slightly more complicated.
<re_irc> <> Provenance is not ownership, it's more limited than that.
<re_irc> <> ```C
fabic has quit [Ping timeout: 246 seconds]
<re_irc> <> hmm, maybe even that won't work. oh well, i'll try anyway (and then I'm going to bed and hopefully someone smarter will tell you where I'm wrong)
<re_irc> <> `array` is actually an array, but when you look at it the wrong way it becomes a pointer because C is a good language. that pointer will have provenance over the whole array.
<re_irc> <> the pointer `a` will also have provenance over the array, because the pointer it's created from also has that provenance. not sure if it's equal, but it's functionally equiv. for this example.
<re_irc> <> `b` is not a pointer, it doesn't know or care about any except for the number it thinks it holds.
<re_irc> <> I think it would be more correct to say that {0} is actually an array (in Rust it would be something like [0;10]), and `array` is an int* that points to the first address of that array.
<re_irc> <> also, maybe relevant that `c[1]` is `c+1`, because that's actually pointer arithmetic and not really an indexing operation.
<re_irc> <> You meant to do `f((uintptr_t)a)`, right ?
<re_irc> <> yeah. tired, sorry.
<re_irc> <> How would I get the provenance of the whole array back in `f` ?
<re_irc> <> not convert it to an integer to begin with
<re_irc> <> other than that... sorry, not sure.
<re_irc> <> So, does that imply that you can only DMA one byte at a time in the C ?
<re_irc> <> I.e given that it's impossible on the C abstract machine to get the provenance back of the whole array, the compiler can consider that any other element (apart from the first one) doesn't change and const propagate reads ?
<re_irc> <> DMA is conceptually equivalent to passing that memory area to another thread of execution that is completely opaque to your program
<re_irc> <> provenance is kind of orthogonal to it, isn't it? it means you can't materialize pointers from thin air, but that's it
<re_irc> <> I usual model it like that too, but isn't passing pointers to another thread, it's passing integers
<re_irc> <> You have to cast it to i.e. u32 to write to the register
<re_irc> <> If the thread can't cast it back to a pointer and use it, then even if it's opaque, the compiler can still optimize around it
<re_irc> <> you need a compiler barrier, a way to signal that the object escapes, yes
<re_irc> <> Yep, you need a pointer escape and a compiler barrier for sync (given that it's a "thread)
<re_irc> <> 9names: > c is pointer, but it only has provenance over the integer that lives at the 5th element of the array
<re_irc> <> that's not true, in C the provenance is always the entire "allocation"
<re_irc> <> so the entire array
<re_irc> <> adamgreig: After some playing around I came to the conclusion that passing the clock to my driver module causes the problem. But I have no clue how to solve that.
<re_irc> <> My question is, can you escape a pointer by just escaping its integer representation, or do you need more (provenance or something else) ?
<re_irc> <> in C it's not specified what happens to provenance when you cast it through integers, I think
<re_irc> <> so I don't think it's guaranteed that you can "launder" provenance like that, no
<re_irc> <> Maybe somehow to `unint_ptr`, but almost nothing
<re_irc> <> But yeah, all I'm talking is outside of the C spec
<re_irc> <> But you can't really model DMA with it, anyway
<re_irc> <> (I think)
<re_irc> <> but why would you want to lanuder provenance like that?
<re_irc> <> the provenance is always the entire array
<re_irc> <> in C, I mean
<re_irc> <> it's always OK to take a ptr to the 5th element and then do pointer math to access the rest of the array from the 5th element
<re_irc> <> Even if it's, if integers have no provenance, then pointers casted from integers can't have the provenance necessary to access an automatic variable from another stack (or its own for that matter)
<re_irc> <> I think the key is "integers have no provenance" is not true
<re_irc> <> It's something a questioning yes, but people smarter than me already said otherwise
<re_irc> <> or maybe they do have "no provenance" but as in "they can access anything", not "they can access nothing" (?
<re_irc> <> so the compiler will give up doing certain optimizations...?
<re_irc> <> so that programs doing pointer-integer casts are still valod
<re_irc> <> provenance isn't actually a part of the standard yet, is it?
<re_irc> <> so we're not talking about something well-defined, but rather about what compiler authors wish they could have had
<re_irc> <> It isn't
<re_irc> <> standard does say it's UB to do pointer math to outside the pointer's original allocation
<re_irc> <> yeah, but that's a different question
<re_irc> <> But in the end, they use several optimizations based on that somehow...
<re_irc> <> that's what "causes" provenance isnt it?
<re_irc> <> it's UB to use ptr from allocation A to access data from allocation B
<re_irc> <> so compiler authors said "okay, let's invent this 'provenance' thing that tracks each pointer's allocation to be able to do fun optimizations based on that"
<re_irc> <> yeah
<re_irc> <> and given that nothing in C prevents you from doing all your pointer math by casting them to integers first, compilers have to be pessimistic
<re_irc> <> i would argue that any compiler that doesn't treat the result of a pointer-to-integer conversion being used on the RHS of a volatile store as an escape is buggy
<re_irc> <> and it's not just an issue for DMA
<re_irc> <> Yeah, in the end I think escaping just the integer representation is enough to escape a pointer, but that still clashes a little in my head with the idea that integers don't have provenance
<re_irc> <> mm, maybe a different way of looking at it would be helpful
<re_irc> <> "provenance" isn't real, it's the way in which the invariants compiler authors want to preserve are expressed in terms of the C language
<re_irc> <> so looking at does and what doesn't have provenance is a bit like looking at the shadows of what you're actually interested in, the invariants
<re_irc> <> of course, things will be different once the standard does introduce the concept
<re_irc> <> Yeah, I agree with you, but compiler authors already uses these concepts to justify some optimizations, which I'm not saying if it's right or wrong, just that I would like for it to be more documented, even to help find bugs in the concepts themselves
<re_irc> <> I think everyone wants that
<re_irc> <> but like... trying to do the job of WG21 over at #rust-embedded seems an awfully long-winded way to figure out if you can use DMA with LLVM
<re_irc> <> All of my questioning was to see if someone already saw some of my questions documented, really not asking for hard truths, more asking for opinions
<re_irc> <> Was already mentioned? It nicely covers the issues compiler optimizations run into regarding pointer provenance and casts between pointers and integers.
<re_irc> <> Yep, this is one that says that integer don't (or shouldn't) have provenance
<re_irc> <> it says that LLVM is currently unsound
<re_irc> <> Well yes and no. It's the authors conclusion that integers without provenance would be the best option, but he also mentions the possibility that one could give integers provenance. And lists some disadvantages that choice would have.
<re_irc> <> Makes sense, and I'm questioning if it would be possible to use DMA if integers don't have provenance, but all of this is just "what if" discussions in the end
<re_irc> <> It was just to see if someone already discussed DMA in this context
<re_irc> <> take a look at N2676 §1.3.4
<re_irc> <> §1.4.1 lists a pointer-to-integer conversion as an _exposure operation_
<re_irc> <> which means that something else, the DMA engine in this case, can synthesize back a pointer from the integer representation
<re_irc> <> Thanks, will read that
<re_irc> <> I have gotten JLinkExe and JLinkGdbServer to work, but probe-rs not... if anyone has any idea for how I could proceed to add support for Ambiq Apollo 3 to probe-rs please see the details here:
Amanieu has quit [Ping timeout: 268 seconds]
<re_irc> <> RTT works over cargo-embed + probe-rs :)!
<re_irc> <> bah, GHA doesn't have rust 1.56. I set edition 2021 and my actions fail.
<re_irc> <> Can you use the rust toolchain action to install it? I think I've always used that
<re_irc> <> It can also install a specific version it you have a toolchain.toml
Amanieu has joined #rust-embedded
<re_irc> <> Is there a such thing as a pre-calibrated embedded microphone for ambient noise measurements?
<re_irc> <> I'm lazy and I want to skip the calibration step.
<re_irc> <> In my experience, it takes about 10-14 days until GitHub images are updated.
<re_irc> <> defmt-test depends on probe-run functioning? it flashes the test to the host and then uses rtt through probe-run presumably?
<re_irc> <> yes
<re_irc> <> I had a first contact with probe-run a few days ago. I was wondering that it does not support ITM, because I thought probe-rs supports ITM.
<re_irc> <> I have not fully figured out what switching to RTT means in practice.
<re_irc> <> Initially I thought RTT only works with J-Link, but I tested it with an ST-Link and it worked also.
<re_irc> <> I found some information somewhere that RTT requires to have the debug probe attached (like with semihosting). Is that true?
<Lumpio-> AFAIK the default mode in probe-rs is to not block when a debugger is not attached
<Lumpio-> It'll buffer messages and start dropping them if nobody's reading.
<Lumpio-> Err I mean defmt not probe-rs - what are you using to output?
<re_irc> <> That would be ok.
<Lumpio-> The behavior depends on what RTT implementation you're using on your chip's side.
<re_irc> <> I've seen there is this rtt-logger crate
<re_irc> <> But the docs there are nearly non-existent.
<Lumpio-> If you use it in "NoBlockSkip" mode (the default) it won't break if there is no debugger.
<re_irc> <> Ok, that looks much better.
<re_irc> <> What is the "cost" to leave RTT logging into the dark? With ITM it nearly nothing due to hardware support.
<Lumpio-> Probably even less than with ITM
<Lumpio-> Well, unless you detect whether a debugger is connected or not.
<Lumpio-> This RTT implementation doesn't know if a debugger is connected or not, so it'll run all the formatting and stringifying code whether it's there or not
<Lumpio-> ...but then just discard the whole thing
<re_irc> <> That's ok for testing.
<Lumpio-> All "RTT" is on the microcontroller side is a buffer in memory it memcpy's messages into
<re_irc> <> I'm asking because I often work on a project with someone else that does not necessarily have the same setup attached.
tokomak has quit [Read error: Connection reset by peer]
emerent has quit [Ping timeout: 246 seconds]
emerent has joined #rust-embedded
Darius has quit [Ping timeout: 260 seconds]