Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ULP serial flush doesn't necessarily work. (IDFGH-14693) #15433

Open
3 tasks done
Tinyu-Zhao opened this issue Feb 20, 2025 · 13 comments
Open
3 tasks done

ULP serial flush doesn't necessarily work. (IDFGH-14693) #15433

Tinyu-Zhao opened this issue Feb 20, 2025 · 13 comments
Assignees
Labels
Awaiting Response awaiting a response from the author Status: Opened Issue is new Type: Bug bugs in IDF

Comments

@Tinyu-Zhao
Copy link

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.

ESP-IDF Master bracnh :C71d74e2

Espressif SoC revision.

ESP32-C6FH4 (QFN32) (revision v0.1)

Operating System used.

macOS

How did you build your project?

VS Code IDE

If you are using Windows, please specify command line type.

None

Development Kit.

Custom Board

Power Supply used.

USB

What is the expected behavior?

When I use 'lp_core_uart_tx_flush(LP_UART_NUM_0)', all the contents of the serial buffer will be sent.

What is the actual behavior?

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "ulp_lp_core_i2c.h"
#include "ulp_lp_core_print.h"
#include "ulp_lp_core_uart.h"
#include "ulp_lp_core_utils.h"
#include "sths34pf80/include/lpsths34pf80.h"
#include "sths34pf80_reg.h"
#define LP_I2C_TRANS_TIMEOUT_CYCLES 7500
#define LP_I2C_TRANS_WAIT_FOREVER   -1

#define STHS34PF80_I2C_ADDR 0x5A

static lpsths34pf80_t lp_sths34pf80;
static uint32_t sensor_on        = 0;
volatile uint32_t motionDetect   = 0;
volatile uint32_t presenceDetect = 0;
static uint32_t dataReady;
static sths34pf80_drdy_status_t drdy_status;

int main(void)
{
    static int iteration = 0;
    lp_core_printf("Hello from the LP core!!\r\n");
    lp_core_printf("This program has run %d times\r\n", ++iteration);
    if (!sensor_on) {
        esp_err_t ret = sths34pf80_init(&lp_sths34pf80, I2C_NUM_0, STHS34PF80_I2C_ADDR);
        if (ret != ESP_OK) {
            // Bail and try again
            lp_core_printf("Failed to initialize the sensor, reason: %d\r\n", ret);
        } else {
            lp_core_printf("Sensor initialized successfully\r\n");

            sensor_on = 1;
        }
    } else {
        lp_core_printf("**************************\r\n");
    }
    lp_core_uart_tx_flush(LP_UART_NUM_0);

    return 0;
}
Screen.Recording.2025-02-20.at.14.09.25.mov

This is my program, lp_core_uart_tx_flush(LP_UART_NUM_0) is placed at the end of the program, and it will be executed every time the contents of the ulp core are executed. But as you can see in the video, the first time the ulp core is run, the Sensor initialized successfully only prints half of the content, and the next time the core is returned to the ulp core, the content that was not sent out before is output.

Steps to reproduce.

Run the program in the ulp core.

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "ulp_lp_core_i2c.h"
#include "ulp_lp_core_print.h"
#include "ulp_lp_core_uart.h"
#include "ulp_lp_core_utils.h"
#include "sths34pf80/include/lpsths34pf80.h"
#include "sths34pf80_reg.h"
#define LP_I2C_TRANS_TIMEOUT_CYCLES 7500
#define LP_I2C_TRANS_WAIT_FOREVER   -1

#define STHS34PF80_I2C_ADDR 0x5A

static lpsths34pf80_t lp_sths34pf80;
static uint32_t sensor_on        = 0;
volatile uint32_t motionDetect   = 0;
volatile uint32_t presenceDetect = 0;
static uint32_t dataReady;
static sths34pf80_drdy_status_t drdy_status;

int main(void)
{
    static int iteration = 0;
    lp_core_printf("Hello from the LP core!!\r\n");
    lp_core_printf("This program has run %d times\r\n", ++iteration);
    if (!sensor_on) {
        // sths34pf80_init(&lp_sths34pf80, I2C_NUM_0, STHS34PF80_I2C_ADDR);
        esp_err_t ret = 0;
        if (ret != ESP_OK) {
            // Bail and try again
            lp_core_printf("Failed to initialize the sensor, reason: %d\r\n", ret);
        } else {
            lp_core_printf("Sensor initialized successfully\r\n");

            sensor_on = 1;
        }
    } else {
        lp_core_printf("**************************\r\n");
    }
    lp_core_uart_tx_flush(LP_UART_NUM_0);

    return 0;
}

Debug Logs.


More Information.

No response

@Tinyu-Zhao Tinyu-Zhao added the Type: Bug bugs in IDF label Feb 20, 2025
@github-actions github-actions bot changed the title ULP serial flush doesn't necessarily work. ULP serial flush doesn't necessarily work. (IDFGH-14693) Feb 20, 2025
@espressif-bot espressif-bot added the Status: Opened Issue is new label Feb 20, 2025
@SoucheSouche
Copy link
Collaborator

Hi @Tinyu-Zhao, thanks for reporting the issue. I will take a look at it and come back to you.

@Tinyu-Zhao
Copy link
Author

I can share any code about sths34pf80 if you guys need it;

I think it's very important to be able to output the TX FIFO message in time, although this issue related PR adds the refreshing of the TX FIFO, but at the moment it only refreshes the TX FIFO after the main function is finished. However, when debugging the program, there are inevitably some bugs that make the program go into a blocking mode, so the main function can't finish, and you can't tell what's going wrong by using the serial TX message. However, when debugging the program, there will inevitably be some bugs that will cause the program to block, and the main function will not be able to finish, and it is not possible to determine the problem through the serial TX message, so I think it would be better if the TX FIFO can be flushed automatically when using lp_core_printf.

Moreover, the API in ulp_lp_core_i2c is not like the API in i2c_driver, there will be communication timeout and other logs actively output during the use, I can only use esp_err_t ret = lp_core_i2c_master_read_from_device(...) Then lp_core_printf to see if there is an error, and then back to the problem I mentioned above “in debugging the program, there will inevitably be some bugs that will make the program will enter the blocking, can not make the main function to end, and at this time there is no way to determine the problem through the serial port TX messages”, in the use of the ulp core I have encountered these problems so that the program can run in accordance with the expected It's hard to run the program as expected.

@SoucheSouche
Copy link
Collaborator

Can you share the ulp_lp_core_cfg_t you are passing to ulp_lp_core_run ?

@SoucheSouche
Copy link
Collaborator

I ran the code you provided to reproduce the issue but I can't see it happening locally.

Can you confirm that the problem occurs for you when running

int main(void)
{
    static int iteration = 0;
    lp_core_printf("Hello from the LP core!!\r\n");
    lp_core_printf("This program has run %d times\r\n", ++iteration);
    if (!sensor_on) {
        // sths34pf80_init(&lp_sths34pf80, I2C_NUM_0, STHS34PF80_I2C_ADDR);
        esp_err_t ret = 0;
        if (ret != ESP_OK) {
            // Bail and try again
            lp_core_printf("Failed to initialize the sensor, reason: %d\r\n", ret);
        } else {
            lp_core_printf("Sensor initialized successfully\r\n");

            sensor_on = 1;
        }
    } else {
        lp_core_printf("**************************\r\n");
    }
    lp_core_uart_tx_flush(LP_UART_NUM_0);

    return 0;
}

@Tinyu-Zhao
Copy link
Author

Tinyu-Zhao commented Feb 24, 2025

Sorry, I forgot the password of my work computer, my code is only stored here, and I am currently contacting Apple to resolve the issue.

Image

@SoucheSouche
Copy link
Collaborator

@Tinyu-Zhao, no problem, let me know when you resolve this issue.

@espressif-bot espressif-bot added the Awaiting Response awaiting a response from the author label Feb 26, 2025
@Tinyu-Zhao
Copy link
Author

Tinyu-Zhao commented Feb 26, 2025

Sorry to make you wait so long, had to add the sths34pf80_init initialization to reproduce the problem.

ulp_lp_core_cfg_t:

static void lp_core_init(void)
{
    esp_err_t ret = ESP_OK;

    ulp_lp_core_cfg_t cfg = {
        .wakeup_source              = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER,
        .lp_timer_sleep_duration_us = 1000 * 1000,
    };

    /* Load LP core firmware */
    ESP_ERROR_CHECK(ulp_lp_core_load_binary(lp_core_main_bin_start, (lp_core_main_bin_end - lp_core_main_bin_start)));

    /* Run LP core */
    ESP_ERROR_CHECK(ulp_lp_core_run(&cfg));

    printf("LP core loaded with firmware successfully\n");
}
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "ulp_lp_core_i2c.h"
#include "ulp_lp_core_print.h"
#include "ulp_lp_core_uart.h"
#include "ulp_lp_core_utils.h"
#include "sths34pf80/include/lpsths34pf80.h"
#include "sths34pf80_reg.h"
#define LP_I2C_TRANS_TIMEOUT_CYCLES 7500
#define LP_I2C_TRANS_WAIT_FOREVER   -1

#define STHS34PF80_I2C_ADDR 0x5A

static lpsths34pf80_t lp_sths34pf80;
static uint32_t sensor_on        = 0;
volatile uint32_t motionDetect   = 0;
volatile uint32_t presenceDetect = 0;
static uint32_t dataReady;
static sths34pf80_drdy_status_t drdy_status;

int main(void)
{
    static int iteration = 0;
    lp_core_printf("Hello from the LP core!!\r\n");
    lp_core_printf("This program has run %d times\r\n", ++iteration);
    if (!sensor_on) {
        esp_err_t ret = sths34pf80_init(&lp_sths34pf80, I2C_NUM_0, STHS34PF80_I2C_ADDR);
        if (ret != ESP_OK) {
            // Bail and try again
            lp_core_printf("Failed to initialize the sensor, reason: %d\r\n", ret);
        } else {
            lp_core_printf("Sensor initialized successfully\r\n");

            sensor_on = 1;
        }
    } else {
        lp_core_printf("**************************\r\n");
    }
    lp_core_uart_tx_flush(LP_UART_NUM_0);

    return 0;
}

``

@Tinyu-Zhao
Copy link
Author

Sorry to make you wait so long, had to add the sths34pf80_init initialization to reproduce the problem.

ulp_lp_core_cfg_t:

static void lp_core_init(void)
{
esp_err_t ret = ESP_OK;

ulp_lp_core_cfg_t cfg = {
    .wakeup_source              = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER,
    .lp_timer_sleep_duration_us = 1000 * 1000,
};

/* Load LP core firmware */
ESP_ERROR_CHECK(ulp_lp_core_load_binary(lp_core_main_bin_start, (lp_core_main_bin_end - lp_core_main_bin_start)));

/* Run LP core */
ESP_ERROR_CHECK(ulp_lp_core_run(&cfg));

printf("LP core loaded with firmware successfully\n");

}
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "ulp_lp_core_i2c.h"
#include "ulp_lp_core_print.h"
#include "ulp_lp_core_uart.h"
#include "ulp_lp_core_utils.h"
#include "sths34pf80/include/lpsths34pf80.h"
#include "sths34pf80_reg.h"
#define LP_I2C_TRANS_TIMEOUT_CYCLES 7500
#define LP_I2C_TRANS_WAIT_FOREVER -1

#define STHS34PF80_I2C_ADDR 0x5A

static lpsths34pf80_t lp_sths34pf80;
static uint32_t sensor_on = 0;
volatile uint32_t motionDetect = 0;
volatile uint32_t presenceDetect = 0;
static uint32_t dataReady;
static sths34pf80_drdy_status_t drdy_status;

int main(void)
{
static int iteration = 0;
lp_core_printf("Hello from the LP core!!\r\n");
lp_core_printf("This program has run %d times\r\n", ++iteration);
if (!sensor_on) {
esp_err_t ret = sths34pf80_init(&lp_sths34pf80, I2C_NUM_0, STHS34PF80_I2C_ADDR);
if (ret != ESP_OK) {
// Bail and try again
lp_core_printf("Failed to initialize the sensor, reason: %d\r\n", ret);
} else {
lp_core_printf("Sensor initialized successfully\r\n");

        sensor_on = 1;
    }
} else {
    lp_core_printf("**************************\r\n");
}
lp_core_uart_tx_flush(LP_UART_NUM_0);

return 0;

}

``

I shared the minimal project with you, in which the sths34pf80 repository is a submodule of the ulp repository, I think the problem may be caused by the I2C ULP blocking, can not be executed to refresh the TX FIFO, just my guess.

@SoucheSouche
Copy link
Collaborator

Hi @Tinyu-Zhao, I tried to replace the sensor init by a delay bigger than the timer period but still could not reproduce your issue.
The timer used to trigger the main() from the lp core is done in the way that it is reset AFTER the main returns. So it does not matter how much time is spent in the sensor init function, eventually the rest of the code in the main will be executed.

Furthermore, the uart tx flush function basically just waits for tx buffer to be empty and returns, it does not perform any action of its own so I have hard time understanding how your issue can occur.

Could you share the code of sths34pf80_init ?

@Tinyu-Zhao
Copy link
Author

Of course, I have invited you to the repository and this repository . You can click this link to accept it.

It's just a matter of incomplete TX FIFO sends.

I've also found that sometimes the program seems to go into a “dead loop” when reading one more register, without any message output!

@sudeep-mohanty
Copy link
Collaborator

sudeep-mohanty commented Feb 27, 2025

Hi @Tinyu-Zhao,
Thank you for providing the source files. While I couldn't reproduce the issue locally, I believe that the problem could lie in the lp_core_uart_tx_flush() API which is not waiting for the LP UART Tx line to be idle. Could you please help try this patch at your end and let us know if it helps with the issue?

lp_uart_flush.patch

@Tinyu-Zhao
Copy link
Author

Hi @Tinyu-Zhao, Thank you for providing the source files. While I couldn't reproduce the issue locally, I believe that the problem could lie in the lp_uart_tx_flush() API which is not waiting for the LP UART Tx line to be idle. Could you please help try this patch at your end and let us know if it helps with the issue?

lp_uart_flush.patch

This patch is useful, it solves the problem of not being able to send out the FIFO, thank you.

@sudeep-mohanty
Copy link
Collaborator

Thanks for the confirmation, @Tinyu-Zhao. We shall add this fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting Response awaiting a response from the author Status: Opened Issue is new Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

4 participants