STM32F3 Discovery, OV7670

I have an STM32F3 Discovery board like the one used in the Embedded Rust book, and I'm trying to get it to work with an OV7670 camera module. I wasn't able to get sensible pixel data, so I decided to scale back and just see if I could communicate with it using I2C, and I couldn't even get that to work. :pensive:

3V3 is connected to 3V on the F3 board.
GND is connected to ground.
SIOC is connected to PB6.
SIOD is connected to PB7.
XCLK is connected to PA8.
RESET is connected to 3V.
PWDN is connected to ground.
Here's the repo with hopefully minimal test code:

Here's the output:

hseon  false
hserdy false
hsion  true
hsirdy true
pllon  true
pllrdy true
pllmul 4
pllsrc false
sws    2
mco    4
mcof   true
before write_read

Unfortunately, I have never used this OV7670 module before, so I don't know if it's functional. I also don't have an oscilloscope, so I can't be sure that XCLK is getting 24MHz clock. I'm hoping someone will just see something crazy in the code, or that I'm missing something important, or that I need more electronics stuff like resistors.

Thanks for any help!

It might be worth getting a cheap sigrok-compatible logic analyser (I got the £10 (circa USD 13) "Hobby Components" 8 channel USB one to debug some 1-wire stuff). The one I got (and most of the cheap ones) are only 24MHz max, but you might be able to use it during debug if you can clock the module down to a lower frequency?

Thanks very much for the suggestion -- I wasn't sure what device would be good, and a lot of them are expensive. I got that one ordered. IIRC the OV7670 datasheet says that the external clock can be as low as 10MHz, and I've heard people have gotten it to work as low as 8MHz. I'm really looking forward to seeing if a clock is really happening on PA8. Thanks again.

I finally got my logic analyzer. Here's how PA8 looks in PulseView:

If the OV7670 datasheet says to provide an external clock signal between 10 and 48MHz, does this look good?

That's a 6 MHz signal, so it's probably too slow then (I don't know the OV7670).
It says 12 MHz, but that's for a half period.

That's just the kind of feedback I needed. I'll configure the trace to only count one or other of the edges and get that between 10 and 48MHz. Thanks!

OK, so I seem to have a good clock on PA8 now. Having provided a good clock to the camera module, I should be able to talk to it using I2C (SCCB). In the process of setting up the f3::hal::i2c::I2c, I do

let mut rcc = dp.RCC.constrain();
let mut flash = dp.FLASH.constrain();
let clocks = rcc.cfgr.freeze(&mut flash.acr);

The last line with the freeze seems to hose the clock on PA8. Is this by design?

And then the constrained version of RCC doesn't seem to support doing all the nitty gritty stuff I did to set up that clock. I don't understand.

Hmm, I'm going crazy here. I've painstakingly translated every line of a seemingly-working i2c example from libopencm3, and now my write_read to what should be the address of the camera returns Err(Arbitration). Via my logic analyzer, I can see that SDA is pulled low, maybe by the camera module. Is there any other way to configure the SDA pin other than into_af4? Any ideas would be appreciated. Thanks.

After a long and difficult struggle, I got communication working between my F3 board and an OV7670 by writing weird SCCB functions, just like the "Hacking OV7670" article from 2012 said I should. I just couldn't believe it was still that way, but it seems to be. Other people with other boards having different I2C implementations seem to skate by as if SCCB is I2C, but boards like the F3 (or this chip or whatever) just don't seem to work and don't have some mitigations that are available on other chips, like telling the I2C implementation to ignore NACK.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.