I wanted to work on some embedded Rust, so I decided to get one of ST's STM32F3DISCOVERY boards.

It has a bunch of features, including the STM32F303VCT6 IC, which has 256 KiB of flash memory and 48-KiB of RAM. There are headers for all of the pins on the STM32F303.

I ran through the directions in the Embedded Rust Book to set up the toolchain. In the last year since I played aroumd with embedded Rust + the brew / cargo setup process, this has gotten a lot, lot easier. Everything just seemed to work for me.

I had a number of OLED screens left from parts for the Ornament and Crime -> an open source Eurorack / modular synthesizer module that uses a SH1106 screen with 7-pin interface. The pins on mine were GND - VDD - SCK - SDA - RES - DC - CS.

The SH1106 crate has example code, but not built for the F3, so it needed some edits: especially in selecting the correct pins and AFR for I2C vs serial connections.

Rust's compile time checks were actually pretty amazing here: selecting the wrong pin would throw an error before it even ran:

1
let i2c = I2c::i2c1(
2
`^^^^^^^^^ the trait 
3
`f3::stm32f30x_hal::i2c::SdaPin<f3::stm32f30x_hal::stm32f30x::I2C1>` 
4
is not implemented for 
5
`f3::stm32f30x_hal::gpio::gpioa::PA10<f3::stm32f30x_hal::gpio::AF4>`

Or, in other words: you've tried to use pin PA10 in alternate function mode 4 (AF4) as an SdaPin in your I2C1 connection, and that mode isn't supported for this pin.

This alternate functions table from the datasheet shows the correct pins, at least for I2C2 (a different interface than I2C1, but using this for now):

STM32F303VC Port A Alternate Functions