I2C not working on non-standard pins on STM32f303k8 (custom hardware)

I am having a strange problem trying to use PA_14 and PA_15 for I2C on STM32F303K8.

I just received my custom board with an STM32F303K8. To map the pins and avoid conflicts, I used STM32CubeMX. I enabled I2C1, which defaulted to pins PA_14 and PA_15 for SDA and SCL respectively. I used these defaults, and only today found out that the default for mbed (or at least the one on their pinout page) is PB_7 and PB_6. I already connected pins PA_14 and PA_15 to the I2C bus on my board and I use PB_6 and PB_7 as digital pins for something else.

This should be no problem though, right? I just need to specify I2C i2c (PA_14, PA_15) when instantiating my i2c instance. This does not work. Not only does it not connect to my sensor, but it seems that the processor halts immediately.

As the comments suggest, even instantiating i2c on pin PA_15 (PA_14 seems fine though?) results in the processor halting. No more logs in my serial terminal. Unfortunately, this board doesn’t have any leds, but I could solder a through hole one on a digital pin if you think it’s a required troubleshooting step.

#include <mbed.h>

// I2C i2c(PA_14, PA_15);  <-- Halts processor if commented out
// I2C i2c(PB_7, PB_6); <-- This is fine
// I2C i2c(PA_14, PB_6);  <-- Even this is fine
// I2C i2c(PB_7, PA_15);  <-- This is NOT fine

static BufferedSerial serial_port(PA_9, PA_10, 9600);

FileHandle *mbed::mbed_override_console(int fd) {
	return &serial_port;
}

int main() {
	// Nothing to do with I2C after instantiation
	while (true) {
		printf(
			"Mbed OS version %d.%d.%d\n",
			MBED_MAJOR_VERSION,
			MBED_MINOR_VERSION,
			MBED_PATCH_VERSION
		);
		thread_sleep_for(100);
	}
}

I scoped PA_14 and PA_15. Both are normally 3.3V (pullup as required by I2C). When I push the reset button, SDA dips down a few millivolt, but only when I hold the button, it’s not sending data. SCL doesn’t budge.

I tried using STM32CubeMX to generate some code using their HAL by specifying these pins, and it works fine.

Am I doing something wrong or did I find a bug? Is there any way to get I2C working with mbed on these pins? I’d rather not write in ST’s HAL and I’d rather not cut traces on my board.

1 Like

Hello,

maybe I am wrong because I am not experienced with a custom target.
But are sure you have pin map correctly set?

In default is the pin PA_15 set as console RX and also it is cut out from I2C pinmap.
So when you call I2C i2c(PA_14, PA_15) it will crash because of pinmap error - Error 0x80010130 pinmap not found for peripheral .You can not see that because you re-target the default console after the IC2.

Try to retarget default console before I2C constructor call and you will see.

BR, Jan

1 Like

Hello Jan,

Thank you so much! Just telling me to put my console redirect before the constructor has already helped me so much! I am getting error messages now.

You are correct. I am getting 0x80010130. The links are helpful. I did not know about these definitions. I thought simply changing the pin in the constructor was enough. I will look into changing these definitions to so that I get my pins back, but I have never done this before, so any hints would be greatly appreciated.

Thank you once again for the help. I am very grateful.

Marcel

For anyone else having a similar issue, I was able to resolve this by overwriting PinMap_I2C_SCL before instantiating I2C.

I copy-pasted the PinMap_I2C_SCL table from Jan’s helpful link, an uncommented the line for PA_15. I also had to change MBED_WEAK with extern.
In the end, I did not need to overwrite MBED_CONF_TARGET_STDIO_UART_TX or MBED_CONF_TARGET_STDIO_UART_RX.

The final code is below:

#include <mbed.h>

// NOTE: This comes earlier now
static BufferedSerial serial_port(PA_9, PA_10, 9600);
FileHandle *mbed::mbed_override_console(int fd) {
	return &serial_port;
}

extern const PinMap PinMap_I2C_SCL[] = {
	{PA_15, I2C_1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)},
	{PB_6, I2C_1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)},
	{NC, NC, 0}
};
I2C i2c(PA_14, PA_15);

int main() {
	while (true) {
		printf(
			"Mbed OS version %d.%d.%d\n",
			MBED_MAJOR_VERSION,
			MBED_MINOR_VERSION,
			MBED_PATCH_VERSION
		);
		thread_sleep_for(100);
	}
}

Jan’s comment about overwriting the serial console before instantiating other classes was instrumental in troubleshooting this. I would definitely recommend putting this part as early as possible.

There might be some other ways to do it too, if interested: STDIO - | Mbed

This also seems related: How to have custom PeripheralPins.c on MBED 5 - Question | Mbed

Thanks again, @JohnnyK Jan. You really saved me. Can I give you a tip? Buy yourself a coffee or something?

You are welcome. If I can I gladly help.

About STDIO

About Custom targets

BR, Jan