<re_irc>
<ignormies> Hey guys fairly new to Embedded Rust. I'm trying to use transmit-only SPI on an stm32f103 to ~implement the WS2812 protocol for a strip of neopixels I have. I'm having a couple issues:
<re_irc>
1. The protocol is supposed to be active-high, but it seems that SPI itself is expected to be active-low. Is there a way to override this? Potential workarounds I've considered are just always sending a 0 as my first word in transmission
<re_irc>
2. I'm having a hard time setting my clock/SPI speeds to get the frequency I want. I'm looking for a 3 MHz signal, but using "Spi::spi2(dp.SPI2, (NoSck, NoMiso, neopixel_mosi), MODE_0, 3.MHz(), clocks)" is giving me a ~4 MHz signal. I've tried messing with the "sysclk" and "pclk1" speeds on my RCC CFGR, but doing so just makes my signal speed even more off.
<re_irc>
3. There's a huge gap between my sent bytes. I'm using "embedded_hal::blocking::spi::Write::write" (see following screenshot)
<re_irc>
<ignormies> Hey guys fairly new to Embedded Rust. I'm trying to use transmit-only SPI on an stm32f103 to ~implement the WS2812 protocol for a strip of neopixels I have. I'm having a couple issues:
<re_irc>
1. The protocol is supposed to be active-high, but it seems that SPI itself is expected to be active-low. Is there a way to override this? Potential workarounds I've considered are just always sending a 0 as my first word in transmission
<re_irc>
2. I'm having a hard time setting my clock/SPI speeds to get the frequency I want. I'm looking for a 3 MHz signal, but using "Spi::spi2(dp.SPI2, (NoSck, NoMiso, neopixel_mosi), MODE_0, 3.MHz(), clocks)" is giving me a ~4 MHz signal. I've tried messing with the "sysclk" and "pclk1" speeds on my RCC CFGR, but doing so just makes my signal speed even more off.
<re_irc>
3. There's a huge gap between my sent bytes. I'm using "embedded_hal::blocking::spi::Write::write" (see following screenshot)
<re_irc>
Happy to provide code snippets if that would be helpful
<re_irc>
<adamgreig> ignormies: have you seen the ws2812-spi crate (https://crates.io/crates/ws2812-spi)? if you just want to get some things lit up that might turn out easier
<re_irc>
<adamgreig> the timing is tricky because the stm32f103 can only divide the system clock by a few fixed ratios, like /2, /4, /8, and so on
<re_irc>
<adamgreig> so if you have a 16MHz system clock, you can do 2, 4, or 8 MHz, but 3MHz isn't possible
<re_irc>
<adamgreig> if you can set the system clock to something that's a multiple of what you want, that should work better, timing-wise
<re_irc>
<adamgreig> the gaps between transmissions will definitely ruin a timing-sensitive protocol like ws2812 as well - are you using stm32f1xx-hal to provide the spi driver? and are you building with "--release" to enable optimisations?
<re_irc>
<ignormies> > have you seen the ws2812-spi crate
<re_irc>
> I have and I wasn't able to get it to work. I get Overrun SPI errors whenever I try sending data.
<re_irc>
<adamgreig> (from the snippet you gave I guess you are using stm32f1xx-hal, I don't have much experience with it but I'd expect if you're providing it a whole block of bytes to write, there shouldn't be big gaps between them)
<re_irc>
<ignormies> ->
<re_irc>
<adamgreig> hmm, maybe your system clock is too slow to keep up? do you know what frequency sysclk and pclk1 etc are?
<re_irc>
<adamgreig> I think you should try and run at 48MHz using the PLL, and then /16 gives you exactly 3MHz SPI clock
<re_irc>
<ignormies> > are you using stm32f1xx-hal to provide the spi driver
<re_irc>
> and are you building with --release to enable optimisations
<re_irc>
yes
<re_irc>
I'm building with "opt-level = "z"" actually. (Not sure if I can use "--release" at the same time; didn't check). For some reason my not-that-large program wasn't fitting in FLASH and the size optimization was (what I thought to be) a quick workaround until I investigated that further. Could that be problematic?
<re_irc>
<adamgreig> and then make sure to build with --release (if you're using cargo-embed or probe-run, make sure to have --release when you call those commands) to make sure optimisations are on
<re_irc>
<adamgreig> using --release tells cargo to use the release profile, which by default is opt-level=3 but you can override to opt-level=z
<re_irc>
<adamgreig> if you're not specifying --release then probably a lot of optimisations aren't being turned on, though it's a surprise if it's still not fitting in flash
<re_irc>
<adamgreig> I'd try without opt-level=z and just with --release
<re_irc>
<adamgreig> how are you programming the chip?
<re_irc>
<ignormies> > do you know what frequency sysclk and pclk1 etc are?
<re_irc>
Is there a way I can find out without manually setting them? I'm currently just doing "rcc.cfgr.freeze(&mut flash.acr);" (but have tried setting them manually to weird results). I can look at the datasheet for their max speeds -- is that what the hal defaults to?
<re_irc>
<adamgreig> I expect the HAL defaults to just running off the 8MHz "HSI" (high-speed internal), and not enabling the PLL at all
<re_irc>
<ignormies> > how are you programming the chip?
<re_irc>
I'm using "cargo-embed" right now. My linker script looks like:
<re_irc>
<adamgreig> linker script looks fine, I guess I'm just surprised you exceeded 64K of flash with a small program, even without optimisations
<re_irc>
<adamgreig> anyway "cargo embed --release" should be what you want, then
<re_irc>
<adamgreig> by the way, the Overrun error from stm32f1xx-hal occurs when data was received that wasn't read, but for ws2812 you aren't reading the data anyway (hence the overflow), so I'm not sure why you were getting that error, maybe something wasn't set up right or was expecting data to be read
<re_irc>
<adamgreig> if you have pclk1 at 24MHz then the SPI should be able to get exactly 3MHz, and hopefully --release is enough to stop there being gaps between bytes
<re_irc>
<adamgreig> you could also try using the "spi_write()" method from stm32f1xx-hal which is designed for efficient transmit-only of a block of data
<re_irc>
<ignormies> adamgreig: I thought that's what I was doing by using "embedded_hal::blocking::spi::Write::write". Is it not?
<re_irc>
<burrbull> Yes, it uses it internally
<re_irc>
<adamgreig> oh, yea, it is the same
<re_irc>
<burrbull> adamgreig: should we use "spi_write" like implementations in other crates?
<re_irc>
<burrbull> f4?
starblue has joined #rust-embedded
<re_irc>
<adamgreig> for write-only I guess it makes sense? I haven't looked at the details