I’ve built the Zephyr SSD1306 example on both nRF52840 dongle and a Black Pill (stm32f411ce), after adding the I2C overlays for each of the boards. Since I haven’t yet got my nRF52840 dongle setup for a breadboard and J-Link debug, I debugged the sample application on the stm32f411ce.
This is a rather lengthy post but I wanted to share more details and solicit feedback.
Here are my environment and Zephyr settings plus the serial debug output from the stm32f411ce.
Environment: Mac OS Mojave 10.14.6
PlatformIO Core: 5.0.3
Platform: ststm32
Framework: Zephyr
Target: stm32f411ce - Black Pill
Display: SSD1306 OLED
Debug: ST-Link V2
SSD1306 Sample: Stock example from “/.platformio/packages/framework-zephyr/samples/drivers/display”
platform.ini:
[platformio]
default_envs = stm32
[env:stm32]
platform = ststm32
framework = zephyr
board = blackpill_f411ce
build_flags = -DSHIELD=ssd1306_128x64
upload_protocol = stlink
debug_tool = stlink
debug_init_break = tbreak main
monitor_speed = 115200
Zephyr CMakeLists.txt (standard boilerplate):
cmake_minimum_required(VERSION 3.13.1)
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(zephyr_ssd1306)
FILE(GLOB app_sources ../src/*.c*)
target_sources(app PRIVATE ${app_sources})
Zephyr prj.conf:
CONFIG_HEAP_MEM_POOL_SIZE=16384
CONFIG_LOG=y
CONFIG_DISPLAY=y
CONFIG_GPIO=y
CONFIG_I2C=y
CONFIG_PRINTK=y
Zephyr Overlay: blackpill_f411ce.overlay
&arduino_i2c {
status = "okay";
ssd1306@3c {
compatible = "solomon,ssd1306fb";
reg = <0x3c>;
label = "SSD1306";
width = <128>;
height = <64>;
segment-offset = <0>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <63>;
segment-remap;
com-invdir;
prechargep = <0x22>;
};
};
zephyr.dts (from .pio/build/stm32/zephyr): i2c1 entry
i2c1: arduino_i2c: i2c@40005400 {
compatible = "st,stm32-i2c-v1";
clock-frequency = < 0x61a80 >;
#address-cells = < 0x1 >;
#size-cells = < 0x0 >;
reg = < 0x40005400 0x400 >;
clocks = < &rcc 0x2 0x200000 >;
interrupts = < 0x1f 0x0 >, < 0x20 0x0 >;
interrupt-names = "event", "error";
status = "okay";
label = "I2C_1";
ssd1306@3c {
compatible = "solomon,ssd1306fb";
reg = < 0x3c >;
label = "SSD1306";
width = < 0x80 >;
height = < 0x40 >;
segment-offset = < 0x0 >;
page-offset = < 0x0 >;
display-offset = < 0x0 >;
multiplex-ratio = < 0x3f >;
segment-remap;
com-invdir;
prechargep = < 0x22 >;
};
main.c code snippet:
#if DT_NODE_HAS_STATUS(DT_INST(0, solomon_ssd1306fb), okay)
#define DISPLAY_DEV_NAME DT_LABEL(DT_INST(0, solomon_ssd1306fb))
#endif
…
…
void main(void)
{
…
…
printk(“Target: STM32f411ce - Black Pill\n”);
LOG_INF("Display sample for %s", DISPLAY_DEV_NAME);
display_dev = device_get_binding(DISPLAY_DEV_NAME);
if (display_dev == NULL) {
LOG_ERR("Device %s not found. Aborting sample.",
DISPLAY_DEV_NAME);
RETURN_FROM_MAIN(1);
}
display_get_capabilities(display_dev, &capabilities);
…
…
RETURN_FROM_MAIN(0);
}
stm32f411ce target serial output:
12:54:05.135 -> *** Booting Zephyr OS build zephyr-v20400 ***
12:54:05.135 -> Target: STM32f411ce - Black Pill
12:54:05.135 -> [00:00:00.007,000] e[0m sample: Display sample for SSD1306e[0m
12:54:05.135 -> [00:00:00.007,000] e[1;31m sample: Device SSD1306 not found. Aborting sample.e[0m
Under debug, device_get_binding() returns NULL, and therefore never invokes display_get_capabilities().
The SSD1306 overlay was automatically added the generated zephyr.dts.
Unlike the nrf52840_dongle, I noticed that arduino_i2c entry for the stm32f411ce doesn’t
have the SCL/SDA pin settings.
nrf52840_dongle.overlay:
i2c0: arduino_i2c: i2c@40003000 {
#address-cells = < 0x1 >;
#size-cells = < 0x0 >;
reg = < 0x40003000 0x1000 >;
clock-frequency = < 0x186a0 >;
interrupts = < 0x3 0x1 >;
status = "okay";
label = "I2C_0";
compatible = "nordic,nrf-twi";
sda-pin = < 0x1f >;
scl-pin = < 0x1d >;
ssd1306@3c {
compatible = "solomon,ssd1306fb";
reg = < 0x3c >;
label = "SSD1306";
width = < 0x80 >;
height = < 0x40 >;
segment-offset = < 0x0 >;
page-offset = < 0x0 >;
display-offset = < 0x0 >;
multiplex-ratio = < 0x3f >;
segment-remap;
com-invdir;
prechargep = < 0x22 >;
};
I use the P0.29 (0x1d) & P0.31(0x1f) pins on the nrf52840_dongle for the SSD1306’s SCL/SCDA
and expected similar entries for the stm32f411ce devicetree.
Pins P0.29/P.31 on the nrf52840_dongle and pins PB6 (SCL1) & PB7 (SDA1) on the stm32f411ce
work fine with the SSD1306 OLED when using the Arduino framework under PlatformIO.
I suspect that there may be an issue with the Zephyr devicetree configuration, that is the cause.
What am I missing or doing incorrectly to configure the Zephyr display sample?
Do I need to include the “solomon,ssd1306fb.yaml” explicitly in PlatformIO Zephyr folder?
If anyone has managed to get the SSD1306 display running successfully with the Zephyr framework under PlatformIO, please share info.
Any suggestions would be greatly welcomed. Thanks!