Hi,
I would like to use 8ug2 in SPI mode. I have copied Your files into clean project but it crashes during SPI initialization. I have tried VSPI and HSPI, I'm pretty sure my PIN's are ok because this board works when I compile it for Arduino project.
On Arduino I'm using this board:
U8G2_SH1106_128X64_VCOMH0_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 0, /* dc=*/21, /* reset=*/ 5);
This is my main.c
// CLK - GPIO14
#define PIN_CLK 18
// MOSI - GPIO 13
#define PIN_MOSI 23
// RESET - GPIO 26
#define PIN_RESET 5
// DC - GPIO 27
#define PIN_DC 21
// CS - GPIO 15
#define PIN_CS 0
static char tag[] = "test_SSD1306";
void task_test_SSD1306(void *ignore) {
u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;
u8g2_esp32_hal.clk = PIN_CLK;
u8g2_esp32_hal.mosi = PIN_MOSI;
u8g2_esp32_hal.cs = PIN_CS;
u8g2_esp32_hal.dc = PIN_DC;
u8g2_esp32_hal.reset = PIN_RESET;
u8g2_esp32_hal_init(u8g2_esp32_hal);
u8g2_t u8g2; // a structure which will contain all the data for one display
u8g2_Setup_sh1106_128x64_vcomh0_f(
&u8g2,
U8G2_R0,
u8g2_esp32_spi_byte_cb,
u8g2_esp32_gpio_and_delay_cb); // init u8g2 structure
u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
u8g2_SetPowerSave(&u8g2, 0); // wake up display
u8g2_ClearBuffer(&u8g2);
u8g2_DrawBox(&u8g2, 10,20, 20, 30);
u8g2_SetFont(&u8g2, u8g2_font_ncenB14_tr);
u8g2_DrawStr(&u8g2, 0,15,"Hello World!");
u8g2_SendBuffer(&u8g2);
ESP_LOGD(tag, "All done!");
vTaskDelete(NULL);
}
void app_main(void)
{
//vTaskDelay(1000/portTICK_PERIOD_MS);
xTaskCreatePinnedToCore(&task_test_SSD1306, "task_simple_tests_ssd1306", 8048, NULL, 5, NULL, 0);
}
This is output during start on VSPI and HSPI
rst:0xc (SW_CPU_RESET),boot:0x16 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:4504
load:0x40078000,len:0
ho 12 tail 0 room 4
load:0x40078000,len:12976
entry 0x40078d88
I (53) cpu_start: Pro cpu up.
I (53) cpu_start: Single core mode
I (53) heap_init: Initializing. RAM available for dynamic allocation:
D (56) heap_init: New heap initialised at 0x3ffae6e0
I (61) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
D (67) heap_init: New heap initialised at 0x3ffb22a8
I (72) heap_init: At 3FFB22A8 len 0002DD58 (183 KiB): DRAM
I (79) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (85) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
D (91) heap_init: New heap initialised at 0x4008864c
I (96) heap_init: At 4008864C len 000179B4 (94 KiB): IRAM
I (102) cpu_start: Pro cpu start user code
D (114) clk: RTC_SLOW_CLK calibration value: 3619085
D (49) intr_alloc: Connected src 46 to int 2 (cpu 0)
D (49) intr_alloc: Connected src 57 to int 3 (cpu 0)
D (50) intr_alloc: Connected src 24 to int 9 (cpu 0)
I (55) cpu_start: Starting scheduler on PRO CPU.
D (60) heap_init: New heap initialised at 0x3ffe0440
D (64) heap_init: New heap initialised at 0x3ffe4350
D (69) intr_alloc: Connected src 16 to int 12 (cpu 0)
D (75) u8g2_hal: gpio_and_delay_cb: Received a msg: 40, arg_int: 0, arg_ptr: 0x0
I (82) gpio: GPIO[0]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 1| Intr:0
I (91) gpio: GPIO[5]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 1| Intr:0
I (100) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 1| Intr:0
D (110) u8g2_hal: spi_byte_cb: Received a msg: 20, arg_int: 0, arg_ptr: 0x0
E (117) err: esp_err_t = 257
assertion "0 && "spi_bus_initialize(VSPI_HOST, &bus_config, 1)"" failed: file "/home/franki/apps/qt/examples/SPI-sh1106/main/./u8g2_esp32_hal.c", line 56, function: u8g2_esp32_spi_byteb
abort() was called at PC 0x400d2267 on core 0
Backtrace: 0x40086c14:0x3ffb68f0 0x40086d13:0x3ffb6910 0x400d2267:0x3ffb6930 0x400d2083:0x3ffb6960 0x400dd135:0x3ffb69d0 0x400dc742:0x3ffb69f0 0x400dcfdd:0x3ffb6a10 0x400e1f4d:0x3ffb6a0
Rebooting...
rst:0xc (SW_CPU_RESET),boot:0x16 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:4504
load:0x40078000,len:0
ho 12 tail 0 room 4
load:0x40078000,len:12976
entry 0x40078d88
I (53) cpu_start: Pro cpu up.
I (53) cpu_start: Single core mode
I (53) heap_init: Initializing. RAM available for dynamic allocation:
D (56) heap_init: New heap initialised at 0x3ffae6e0
I (61) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
D (67) heap_init: New heap initialised at 0x3ffb22a8
I (72) heap_init: At 3FFB22A8 len 0002DD58 (183 KiB): DRAM
I (79) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (85) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
D (91) heap_init: New heap initialised at 0x4008864c
I (96) heap_init: At 4008864C len 000179B4 (94 KiB): IRAM
I (102) cpu_start: Pro cpu start user code
D (114) clk: RTC_SLOW_CLK calibration value: 3613862
D (49) intr_alloc: Connected src 46 to int 2 (cpu 0)
D (49) intr_alloc: Connected src 57 to int 3 (cpu 0)
D (50) intr_alloc: Connected src 24 to int 9 (cpu 0)
I (55) cpu_start: Starting scheduler on PRO CPU.
D (60) heap_init: New heap initialised at 0x3ffe0440
D (64) heap_init: New heap initialised at 0x3ffe4350
D (69) intr_alloc: Connected src 16 to int 12 (cpu 0)
D (75) u8g2_hal: gpio_and_delay_cb: Received a msg: 40, arg_int: 0, arg_ptr: 0x0
I (82) gpio: GPIO[0]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 1| Intr:0
I (91) gpio: GPIO[5]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 1| Intr:0
I (100) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 1| Intr:0
D (110) u8g2_hal: spi_byte_cb: Received a msg: 20, arg_int: 0, arg_ptr: 0x0
E (117) err: esp_err_t = 257
assertion "0 && "spi_bus_initialize(HSPI_HOST, &bus_config, 1)"" failed: file "/home/franki/apps/qt/examples/SPI-sh1106/main/./u8g2_esp32_hal.c", line 56, function: u8g2_esp32_spi_byteb
abort() was called at PC 0x400d2267 on core 0
Backtrace: 0x40086c14:0x3ffb68f0 0x40086d13:0x3ffb6910 0x400d2267:0x3ffb6930 0x400d2083:0x3ffb6960 0x400dd135:0x3ffb69d0 0x400dc742:0x3ffb69f0 0x400dcfdd:0x3ffb6a10 0x400e1f4d:0x3ffb6a0
Rebooting...
I would be grateful if You can give my any tpis why it refuses to work ;)
It looks like an memory error:
#define ESP_ERR_NO_MEM 0x101
Best Regards
Marek
I am using this HAL with the ESP_IDF. I am getting the same error as Marek. However I noticed that I am only getting this error when the ESP32 logging component is set to anything other than Info. When the Log level is set to Info, the code runs great.
Does anyone have any idea why this is happening and what can be done to fix it?
Hi Jim
I will try to use U8G2 library again, because due to this problem we had to use something else in our project. Can You share your code that works eg. on a github.
Best Regards
Marek
Here is a turnkey project based on Neil's example:
git clone --recursive https://github.com/JimGaluska/u8g2-esp_idf-example.git
This will compile and run as is, however if you change the log verbosity to anything other than 'Info' the example will crash and burn at the same point, and in the same way as your issue.
Good luck.
Jim
I think I have found out what the issue is and have a fix or workaround (however you want to look at it).
First off, I found out the the issue only happens when I have set the ESP32 clock speed down to the slowest setting; 80Mhz. At higher clock speeds the issue goes away.
The following is a snippet from the file test_SSD1306.c:
void task_test_SSD1306(void *ignore) {
u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;
u8g2_esp32_hal.clk = PIN_CLK;
u8g2_esp32_hal.mosi = PIN_MOSI;
u8g2_esp32_hal.cs = PIN_CS;
u8g2_esp32_hal.dc = PIN_DC;
u8g2_esp32_hal.reset = PIN_RESET;
u8g2_esp32_hal_init(u8g2_esp32_hal);
u8g2_t u8g2; // a structure which will contain all the data for one display
u8g2_Setup_ssd1306_128x64_noname_f(
&u8g2,
U8G2_R0,
u8g2_esp32_spi_byte_cb,
u8g2_esp32_gpio_and_delay_cb); // init u8g2 structure
u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
Function u8g2_esp32_hal_init is implement in the hal as follows::
void u8g2_esp32_hal_init(u8g2_esp32_hal_t u8g2_esp32_hal_param) {
u8g2_esp32_hal = u8g2_esp32_hal_param;
} // u8g2_esp32_hal_init
As you can see, u8g2_esp32_hal_init copies the structure that is passed in by value to a local copy. My theory is that function u8g2_esp32_hal_init returns before the entire contents of the passed in structure is copied to the local structure.. When function u8g2_InitDisplay is called, it makes a callback into the hal where the structure is used to initialize the spi interface before it is fully copied.
My fix/workaround is to add a delay before between when functions u8g2_esp32_hal_init and u8g2_InitDisplay is called as follows:
void task_test_SSD1306(void *ignore) {
u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;
u8g2_esp32_hal.clk = PIN_CLK;
u8g2_esp32_hal.mosi = PIN_MOSI;
u8g2_esp32_hal.cs = PIN_CS;
u8g2_esp32_hal.dc = PIN_DC;
u8g2_esp32_hal.reset = PIN_RESET;
u8g2_esp32_hal_init(u8g2_esp32_hal);
vTaskDelay(1); // <== Insert delay here
u8g2_t u8g2; // a structure which will contain all the data for one display
u8g2_Setup_ssd1306_128x64_noname_f(
&u8g2,
U8G2_R0,
u8g2_esp32_spi_byte_cb,
u8g2_esp32_gpio_and_delay_cb); // init u8g2 structure
u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
On my system, this make the problem go away in all cases that I have tried.
One interesting observation is that placing the delay inside the function u8g2_esp32_hal_init does not work:
void u8g2_esp32_hal_init(u8g2_esp32_hal_t u8g2_esp32_hal_param) {
u8g2_esp32_hal = u8g2_esp32_hal_param;
vTaskDelay(100); // <== Large delays don't work here
} // u8g2_esp32_hal_init
Perhaps vTaskDelay takes away CPU time to the structure copy operation when it is used inside the hal init function and it doesn't remove CPU time when it is used at the higher level.
Jim, many thanks for Your valuable help. We are using u8g2 now in our project.
Best Regards
Marek
@JimGaluska Your fix did it for me as well. I spent a quarter day on this before adding vTaskDelay(1) after calling init and fixing it all. Thanks. Unsure why it works , but your explanation seems good.
Another thing to check: are all your struct elements properly set or cleared?
I ran into a similar crash using the i2c version. I found that u8g2_esp32_i2c_byte_cb() (in u8g2_esp32_hal.c) created a struct i2c_config_t conf, but didn't initialize the clk_flags member. When the call succeeded, clk_flags was 0x0; when it failed, clk_flags was something odd like 0x3FFB55F0. Setting clk_flags to 0 let me do away with vTaskDelays and printfs that had mysteriously been preventing crashes (apparently by pushing stuff around on the stack enough that, when it worked, clk_flags wound up in a clean area).
I saw a similar fix for the SPI version in a pull request: https://github.com/nkolban/esp32-snippets/pull/884
Another thing to check: are all your struct elements properly set or cleared?
I ran into a similar crash using the i2c version. I found that u8g2_esp32_i2c_byte_cb() (in u8g2_esp32_hal.c) created a struct
i2c_config_t conf, but didn't initialize theclk_flagsmember. When the call succeeded, clk_flags was 0x0; when it failed, clk_flags was something odd like 0x3FFB55F0. Setting clk_flags to 0 let me do away with vTaskDelays and printfs that had mysteriously been preventing crashes (apparently by pushing stuff around on the stack enough that, when it worked, clk_flags wound up in a clean area).I saw a similar fix for the SPI version in a pull request: #884
Thanks Adam - this was exactly the problem I had and setting conf.clk_flags=0 as per your suggestion has fixed it
Most helpful comment
I think I have found out what the issue is and have a fix or workaround (however you want to look at it).
First off, I found out the the issue only happens when I have set the ESP32 clock speed down to the slowest setting; 80Mhz. At higher clock speeds the issue goes away.
The following is a snippet from the file test_SSD1306.c:
Function u8g2_esp32_hal_init is implement in the hal as follows::
As you can see, u8g2_esp32_hal_init copies the structure that is passed in by value to a local copy. My theory is that function u8g2_esp32_hal_init returns before the entire contents of the passed in structure is copied to the local structure.. When function u8g2_InitDisplay is called, it makes a callback into the hal where the structure is used to initialize the spi interface before it is fully copied.
My fix/workaround is to add a delay before between when functions u8g2_esp32_hal_init and u8g2_InitDisplay is called as follows:
On my system, this make the problem go away in all cases that I have tried.
One interesting observation is that placing the delay inside the function u8g2_esp32_hal_init does not work:
Perhaps vTaskDelay takes away CPU time to the structure copy operation when it is used inside the hal init function and it doesn't remove CPU time when it is used at the higher level.