ChanServ changed the topic of #rust-embedded to: Welcome to the Rust Embedded IRC channel! Bridged to #rust-embedded:matrix.org and logged at https://libera.irclog.whitequark.org/rust-embedded, code of conduct at https://www.rust-lang.org/conduct.html
rardiol has joined #rust-embedded
dc740 has quit [Remote host closed the connection]
rardiol has quit [Ping timeout: 246 seconds]
<re_irc> <@zaven:matrix.x24.tools> Greetings! So about rcc.cfg.freeze - what is recommended if I will in fact be changing the clocks later? In our C code, when we go into low power mode we switch back to the HSI clock and power down HSE/PLL. On wake we switch pack to PLL. I'm on stm32f103. Also looks like the low power modes aren't implemented yet in hal 0.10, I could take that on if that's so.
rardiol has joined #rust-embedded
fabic has joined #rust-embedded
rardiol has quit [Ping timeout: 246 seconds]
bjc has left #rust-embedded [ERC 5.4.1 (IRC client for GNU Emacs 30.0.50)]
<re_irc> <@sourcebox:matrix.org> : I hope I remember correctly that you're the one that created the "stm32-hal2" crate. I adapted the "serial_nonblocking" example successfully and want to extend it to be able to also transmit data. For this, I need to determine the source of the interrupt inside the handler, but I did not find any method to identify it.
<re_irc> <@ryan-summers:matrix.org> zaven: You're somewhat breaking out of what the HALs support, but you can always unsafely conjure pointers to the RCC and do register manipulation yourself :)
<re_irc> <@ryan-summers:matrix.org> Changing the clocks impacts all of the peripherals, so you'll obviously have to be careful, but this is largely why the HALs don't provide this in a normal API - it's hard to guarantee operation via typestate
<re_irc> <@ryan-summers:matrix.org> Maybe there's a way to do it though! I know in one of my projects we maintain a concept of users-of-a-clock. Then when we sleep, we intuitively look at clock users and figure out the deepest sleep state we can afford. Could probably do something similar with a HAL
brazuca has quit [Quit: Client closed]
<re_irc> <@elephantpie:matrix.org> How is the experience with rust on the ESP-32 S3?/
rardiol has joined #rust-embedded
<re_irc> <@sourcebox:matrix.org> : I only have a little bit of experience with it. If you use the std approach with esp-idf-hal, then you can already do a lot of things because there are bindings to all functions of the IDF. But the compiler itself causes some miscompilation regarding floating points that will hopefully get sorted soon.
dc740 has joined #rust-embedded
brazuca has joined #rust-embedded
brazuca has quit [Quit: Client closed]
<re_irc> <@firefrommoonlight:matrix.org> : In theory you can check the Reference Manual, but in practice the PAC name _may_ be different. I usually troubleshoot until I find it if the RM name doesn't work
<re_irc> <@firefrommoonlight:matrix.org> Which UART line? It's usually "USARTx" or "UARTx"
<re_irc> <@firefrommoonlight:matrix.org> And of note, that example, while it doesn't block for the whole read, blocks a bit on each byte; I should probably replace it with one that uses DMA
<re_irc> <@firefrommoonlight:matrix.org> *Sorry, I misunderstood your question
<re_irc> <@firefrommoonlight:matrix.org> Check the flags in the ISR register
<re_irc> <@firefrommoonlight:matrix.org> if unsafe {}
<re_irc> <@firefrommoonlight:matrix.org> let status = unsafe { (*pac::USART3::ptr()).isr.read() };
<re_irc> if status.idle().bit_is_set() {
<re_irc> else if status.cts().bit_is_set() {
<re_irc> // ..
<re_irc> }
<re_irc> <@firefrommoonlight:matrix.org> I should probably add a helper method for this
<re_irc> <@firefrommoonlight:matrix.org> let status = unsafe { (*pac::USART3::ptr()).isr.read() };
<re_irc> // ..
<re_irc> } else if status.cts().bit_is_set() {
<re_irc> if status.idle().bit_is_set() {
<re_irc> }
<re_irc> <@sourcebox:matrix.org> : I use it with USART2 and the "read_one()" method, so it doesn't block.
<re_irc> <@firefrommoonlight:matrix.org> The difference in the approaches is in that approach, the CPU activates briefly each time that interrupt goes, allowing other processes to occur between bytes. In the DMA approach, the CPU activates at the start and end of the transfer only
<re_irc> <@sourcebox:matrix.org> Yes, but that's ok for my purpose because UART is quite slow and the interrupt doesn't happen so often.
<re_irc> <@sourcebox:matrix.org> What I didn't find is a similar "write_once()" method that does not block.
<re_irc> <@sourcebox:matrix.org> In the existing write method, there is a loop that waits for transfer complete, which is not so nice.
<re_irc> <@firefrommoonlight:matrix.org> You would call "write()" with a small buffer of only the byte you're writing
<re_irc> <@sourcebox:matrix.org> Because normally you don't have to wait for TC because the interrupt is triggered again then TX is empty and then you just send either the next byte or disable the TX interrupt.
<re_irc> <@sourcebox:matrix.org> * when
<re_irc> <@sourcebox:matrix.org> DMA is generally a better approach for all this if you can run it in circular mode, but the main backdraw is the limited number of channels and routing in many STM32 variants without a DMAMUX.
<re_irc> <@firefrommoonlight:matrix.org> Good pt. I mainly use DMAMUX ones where that doesn't come up
<re_irc> <@firefrommoonlight:matrix.org> And UART is so flexible, the specific approach used depends on the protocol - especially if the message size varies
<re_irc> <@firefrommoonlight:matrix.org> Ie, I have one use where I identify the start of a message with a character match, and the end with an idle interrupt. I disable the char match interrupt while reception is happening, then re-enable after
<re_irc> <@sourcebox:matrix.org> I'm using it for MIDI, which is 31250 baud. Messages can be received at any time and the length varies.
<re_irc> <@firefrommoonlight:matrix.org> Tricky!
<re_irc> <@firefrommoonlight:matrix.org> Hopefully they don't collide...
<re_irc> <@sourcebox:matrix.org> Not really. I just put them into a ringbuffer.
<re_irc> <@sourcebox:matrix.org> Then there is a parser that assembles the bytes to a compound message.
<re_irc> <@firefrommoonlight:matrix.org> Clever
<re_irc> <@sourcebox:matrix.org> So basically I want to use 2 ring buffers for send and receive. They are completely independent.
<re_irc> <@sourcebox:matrix.org> This is a different use case to that where you have a protocol with a request/response pattern.
<re_irc> <@sourcebox:matrix.org> Essential streams.
<re_irc> <@sourcebox:matrix.org> * Essentially
<re_irc> <@firefrommoonlight:matrix.org> Interesting. LMK if you have any API ideas to facilitate
<re_irc> <@sourcebox:matrix.org> As I said, as "write_once()" function (or however you want to call it) that does not block. And of course some way to match the interrupt source inside the handler.
<re_irc> <@firefrommoonlight:matrix.org> Done, re checking UART interrupt source:
<re_irc> pub fn check_status_flag(&mut self, flag: UsartInterrupt) -> bool {
<re_irc> <@sourcebox:matrix.org> Yes, that looks good.
<re_irc> /// Checks if a given status flag is set. Returns `true` if the status flag is set. Note that this preforms
<re_irc> <@firefrommoonlight:matrix.org> Done, re checking UART interrupt source:
<re_irc> /// a read each time called. If checking multiple flags, this isn't optimal.
<re_irc> pub fn check_status_flag(&mut self, flag: UsartInterrupt) -> bool {
<re_irc> <@firefrommoonlight:matrix.org> What would the "write" fn do that's different from writing a single byte?
<re_irc> <@firefrommoonlight:matrix.org> * byte buffer?
<re_irc> <@sourcebox:matrix.org> Not do "while self.regs.sr.read().tc().bit_is_clear() {}"
<re_irc> <@firefrommoonlight:matrix.org> Ah
<re_irc> <@firefrommoonlight:matrix.org> Got it
<re_irc> <@firefrommoonlight:matrix.org> Of course
<re_irc> <@sourcebox:matrix.org> The "check_status_flag()", does it need to take "&mut self"?
<re_irc> <@firefrommoonlight:matrix.org> Yes
<re_irc> <@sourcebox:matrix.org> Ok.
<re_irc> <@firefrommoonlight:matrix.org> An alternative would be "usart::check_status_flag()" that doesn't required it
<re_irc> <@sourcebox:matrix.org> No, leave it like it is.
<re_irc> <@sourcebox:matrix.org> Just wondering because it's only reading.
<re_irc> <@firefrommoonlight:matrix.org> My main caveat with it (As seen in the doc comment) is that if you're checking multiple flags, it requires extra reads
<re_irc> <@firefrommoonlight:matrix.org> (Which isn't strictly required since all the flags are on teh same reg)
<re_irc> <@firefrommoonlight:matrix.org> Live on GH
<re_irc> <@sourcebox:matrix.org> Ok, thanks. I'll have a look.
<re_irc> <@sourcebox:matrix.org> So, API-wise I got it working, but I have to setup some hardware to check it.
<re_irc> <@sourcebox:matrix.org> Ok, why is "ReadNotEmpty" and "TransmitEmpty" not applicable? These are the ones I need.
<re_irc> <@firefrommoonlight:matrix.org> Added
dc740 has quit [Remote host closed the connection]
<re_irc> <@sourcebox:matrix.org> : Hmm. Did you push the fixes?
<re_irc> <@sourcebox:matrix.org> : BTW, I noticed some comment about 9-bit data size. Normally, that should just be the parity bit and is automatically set. So nothing to handle manually.
<re_irc> <@sourcebox:matrix.org> Quote from the L4 RM: "When transmitting with the parity enabled (PCE bit set to 1 in the USART_CR1 register),
<re_irc> because it is replaced by the parity."
<re_irc> the value written in the MSB (bit 7 or bit 8 depending on the data length) has no effect
<re_irc> <@firefrommoonlight:matrix.org> Looks like I didn't push!
<re_irc> <@firefrommoonlight:matrix.org> Expect in a few hrs
<re_irc> <@firefrommoonlight:matrix.org> I saw the option for 9-bit data in the RM, but skipped over it. Good to know no action or u16 dtype is required for that
<re_irc> <@sourcebox:matrix.org> 9 bit is just the data width you have to configure when using parity.
<re_irc> <@firefrommoonlight:matrix.org> It seems you can configure 7, 8, or 9 bit words
<re_irc> <@firefrommoonlight:matrix.org> Which is avail in the UsartConfig struct
<re_irc> <@firefrommoonlight:matrix.org> 7 and 8 should just work
<re_irc> <@firefrommoonlight:matrix.org> But 9 is blocked by the u8 type
<re_irc> <@sourcebox:matrix.org> Yes, 9 bit because the parity bit is added to the data size.
<re_irc> <@firefrommoonlight:matrix.org> Thx for the info on that
<re_irc> <@sourcebox:matrix.org> But it's done automatically.
<re_irc> <@sourcebox:matrix.org> Have to see for the RX part though.
<re_irc> <@firefrommoonlight:matrix.org> I'm looking at the M bits in CR1
<re_irc> <@sourcebox:matrix.org> On receive I typically do & 0xFF so a parity bit would be filtered out.
<re_irc> <@sourcebox:matrix.org> This is also what's done in ST HAL
<re_irc> <@sourcebox:matrix.org> Quote: "When receiving with the parity enabled, the value read in the MSB bit is the received parity
<re_irc> bit."
<re_irc> <@firefrommoonlight:matrix.org> Perfect
fabic has quit [Ping timeout: 248 seconds]
dc740 has joined #rust-embedded
<re_irc> <@firefrommoonlight:matrix.org> Pushed
rardiol has quit [Ping timeout: 260 seconds]
rardiol has joined #rust-embedded
rardiol has quit [Ping timeout: 260 seconds]
rardiol has joined #rust-embedded
rardiol has quit [Quit: https://quassel-irc.org - Chat comfortably. Anywhere.]
brazuca has joined #rust-embedded
<re_irc> <@sourcebox:matrix.org> : Thanks! Works now.
dc740 has quit [Remote host closed the connection]
brazuca has quit [Quit: Client closed]
<re_irc> <@cfrenette:matrix.org> Hi! 👋 I'm new to Rust and embedded programming and am writing my first embedded-hal driver crate for the BMA400 Accelerometer (https://github.com/cfrenette/bma400-rs).
<re_irc> Since I'm so new, I wanted to shop around for some feedback (hopefully I'm in the right place?) on what I've built so far in case I need to rework a whole bunch before I implement the last few things, clean it up, write the docs, tests and publish the crate.
<re_irc> <@cfrenette:matrix.org> Of particular note:
<re_irc> - The device instance is generic over two interface types wrapping interfaces each implementing i2c and spi hal traits, respectively because I intend to implement the SPI interface soon.
<re_irc> - Error wrapping: I struggled with this a bit. What I have works if I explicitly ".map()" the associated type "i2c::Error" to my "BMA400Error<E>", but feels off.
<re_irc> - "read_fifo_frames()": The device writes more than just measurements to the buffer, so I wanted to provide more API than just reading and sending the byte array back so the lib consumer doesn't need to dive into the datasheet. I return an iterator over the byte array that parses out the data. Is this too much?
<re_irc> - There are a LOT of configuration registers for this device so I was thinking about splitting off some into conditionally compiled features to maybe save some space, new to embedded so not really sure how big a difference a couple hundred bytes is.
<re_irc> - There's a lot of repetitive code with the configuration and the Java dev in me was screaming for trait objects or something to reuse code. Hopefully a lot of the copy/paste boilerplate doesn't look too dumb, but let me know if I missed an obvious opportunity here!
<re_irc> <@admin:orangemurker.com> : Macros could be a really nice way to abstract repetitive code.