Skip to content

ESP32C5, parlio rx with soft delimeter generate excessive PAD_CLK pulse and failed to capture and count them (IDFGH-17223) #18223

@unclealexchen

Description

@unclealexchen

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.

v6.0-beta1-1452-g48e7e0618d

Espressif SoC revision.

ESP32-C5 (revision v1.0)

Operating System used.

Windows

How did you build your project?

Command line with idf.py

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

CMD

Development Kit.

Custom Board (ESP32C5 + FPGA)

Power Supply used.

USB

What is the expected behavior?

We have been stuck on this issue for months. please help !
我们已经在RX相关的问题上卡了一个多月了,有点无路可走了,急需帮助!

My Custom-designed board have:
ESP32-C5-WROOM-1-N8R8 <-----> FPGA
We try to receive the data from FPGA through 8 bit data bus + PAD_CLK (clock signal genrate by ESP32C5) + RX_EN( rx enable signal generate by ESP32C5).

FPGA只是简单地在PAD_CLK的上升沿递增8位数据总线上的整数:
At the side of FPGA, we simply increase a 8 bit integer on DATA BUS by 1 at the rising edge of PAD_CLK:
以下是FPGA那边的相关代码:

assign DBUS = TX_EN?8'hzz:dbus_write;
always @ (posedge PAD_CLK)
begin
if (RX_EN) begin
dbus_write <= dbus_write + 8'h1;
end
end

ESP32C5收到的数据应该在0 ~ 255之间循环。
At the side of ESP32C5, we use soft delimeter, start rx transaction, try to receive 128 bytes again and again.
The received bytes should be a loop like: 0 , 1, 2, 3, 4, ...., 253, 254, 255, 0, 1, 2, ...

What is the actual behavior?

For the first rx transaction (0 rx transaction):
The received data is right: 234, 235,,....255, 0, 1, 2, .... 105
But from the second rx transaction (1 - 8 rx transaction):
Always a sudden change of the value between 16 & 17 byte.
121 to 233 in 1 rx transaction;
104 to 165 in 2 rx transaction.

第一次传输,收到数据正常,从234循环到255,然后到0,1, 直至105;
从第2次传输开始,总是在第16个字节和第17个字节之间发生突然的数据变化,在1 rx transaction里,从121直接突变为233,在2 rx transacttion里,从104直接突变为165。

Since this kind of sudden change always occurs between the 16th and 17th bytes, one reasonable explanation is that the ESP32C5 generates some PAD_CLK pulses during this period but fails to sample and count them.

由于这些变化总是发生在第16到第17字节之间的固定位置,一种合理解释就是ESP32C5在PAD_CLK上产生了一些脉冲,但却没有采样和计数。

Please help to answer: if the rx unit can generate a similar chip-select signal as tx unit does ?
请帮助回答:RX模块可不可以像TX模块那样在通信期间产生一个使能信号? 这样的话,FPGA可以通过这个使能信号判断是否需要在总线上提供数据?

I (237) sleep_gpio: Configure to isolate all GPIO pins in sleep state
I (244) sleep_gpio: Enable automatic switching of GPIO sleep configuration
I (251) main_task: Started on CPU0
I (251) main_task: Calling app_main()
Begin rx test...
PARLIO_RX_PACKET_SIZE = 128
Open parlio rx successfully.
working!
0 rx transaction:
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,
working!
1 rx transaction:
106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,
working!
2 rx transaction:
89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
working!
3 rx transaction:
21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,
working!
4 rx transaction:
214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,
working!
5 rx transaction:
139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,
working!
6 rx transaction:
58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,
working!
7 rx transaction:
232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,
working!
8 rx transaction:
151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,
working!

Steps to reproduce.

At my side, the problem can easily and steadily repeated.
I first met this problem with ESP-IDF v5.5.2, after upgrade to ESP-IDF v6.0, exactly same problem there.

As you do not have my custom board, it seems not easy to reproduce this issude at your side.
If necessary, I'm happy to travel to your city and try to solve this with you.

Debug Logs.

Not a crash.

Diagnostic report archive.

Not a crash.

More Information.

To help the diagnosis of the problem, I generated a simple project based on blink example.
Below is the core code, for quick review.

`/* Blink Example

This example code is in the Public Domain (or CC0 licensed, at your option.)

Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "led_strip.h"
#include "sdkconfig.h"
#include "driver/parlio_rx.h"

#define DBUS0 3
#define DBUS1 0
#define DBUS2 1
#define DBUS3 6
#define DBUS4 7
#define DBUS5 8
#define DBUS6 9
#define DBUS7 10
#define PAD_CLK 25
#define RX_EN 23 //high active

#define PARLIO_RX_PACKET_SIZE 128

const char *TAG = "BLINK";

typedef struct {
parlio_rx_unit_handle_t unit;
uint8_t *buffer; //用于并口数据接收的DMA兼容缓冲区
volatile bool bufferFilled; //用于接收数据的缓冲区存在尚未处理的数据
parlio_rx_delimiter_handle_t deli; //软界定符
volatile bool ing; //是否有并口数据正在接收中
parlio_receive_config_t receiveConfig;
} ParlioRx;

static ParlioRx rx = {
.unit = NULL,
.buffer = NULL,
.bufferFilled = false,
.deli = NULL,
.ing = false,
.receiveConfig = {
.delimiter = NULL, // 使用上面创建的软帧界定符
.flags = {
.partial_rx_en = false, // 禁用部分接收模式
.indirect_mount = false, // 直接挂载用户缓冲区到 DMA
},
},
};

static bool on_rx_receive_done_callback(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_ctx)
{
gpio_set_level(RX_EN,0);

//停止软帧界定符
parlio_rx_soft_delimiter_start_stop(rx_unit, rx.deli, false);  
rx.ing = false;
rx.bufferFilled = true;
return false;

}

bool openParlioRx() {
if (rx.unit!=NULL){
ESP_LOGE(TAG,"Found rx.unit is not NULL in openParlioRx().");
return false;
}

// 分配 DMA 兼容缓冲区,全生命周期有效,不考虑回收
if (rx.buffer==NULL) {
    rx.buffer = 
        heap_caps_calloc(1, PARLIO_RX_PACKET_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
    if (rx.buffer == NULL) {
        ESP_LOGE(TAG,"Allocation of DMA capatible bufferParlioRx failed!");
        return false;
    }
}

rx.ing = false;

parlio_rx_unit_config_t config = {
    .clk_src = PARLIO_CLK_SRC_DEFAULT,   
    .data_width = 8,                     
    .clk_in_gpio_num = -1,               // 不使用外部时钟源
    .clk_out_gpio_num = PAD_CLK,         // 输出时钟引脚 PAD_CLK
    .valid_gpio_num = -1,                // 据文档,使用soft delimiter时应为-1
    .data_gpio_nums = {
        DBUS0,DBUS1,DBUS2,DBUS3,DBUS4,DBUS5,DBUS6,DBUS7,
    },
    .exp_clk_freq_hz = 10 * 1000 * 1000,        // 期望时钟频率为 10MHz
    .trans_queue_depth = 1,                     // 事务队列深度为 1
    .max_recv_size = PARLIO_RX_PACKET_SIZE, // 最大接收大小,字节
};

ESP_ERROR_CHECK(parlio_new_rx_unit(&config, &rx.unit));  // 创建 RX 单元实例

parlio_rx_event_callbacks_t cbs = {
    .on_partial_receive = NULL,
    .on_receive_done = on_rx_receive_done_callback,
    .on_timeout = NULL
};
ESP_ERROR_CHECK(parlio_rx_unit_register_event_callbacks(rx.unit, &cbs, NULL));

ESP_ERROR_CHECK(parlio_rx_unit_enable(rx.unit, true));   // 使能 RX 单元,并重置事务队列

if (rx.deli == NULL) {
    parlio_rx_soft_delimiter_config_t softConfig = {
        .sample_edge = PARLIO_SAMPLE_EDGE_NEG,       // 负边沿采样
        .bit_pack_order = PARLIO_BIT_PACK_ORDER_MSB, // 从 MSB 开始打包位
        .eof_data_len = PARLIO_RX_PACKET_SIZE,        //x字节后结束帧
        .timeout_ticks = 0,                          // 无超时
    };
    ESP_ERROR_CHECK(parlio_new_rx_soft_delimiter(&softConfig, &rx.deli));
}

printf("Open parlio rx successfully.\n");
return true;

}

void initOutputPins() {
gpio_config_t c = {};
c.intr_type = GPIO_INTR_DISABLE; //disable interrupt
c.mode = GPIO_MODE_OUTPUT; //set as output mode
c.pin_bit_mask = ((1ULL<<RX_EN) | (1ULL<<PAD_CLK));
c.pull_down_en = 1;
c.pull_up_en = 0; //disable pull-up mode
gpio_config(&c);
gpio_set_level(RX_EN,0);
gpio_set_level(PAD_CLK,0);
}

bool parlioReceive() {
if (rx.ing)
return false;

if (rx.unit == NULL) {
    if (!openParlioRx())
        return false;
}

rx.ing = true;
rx.receiveConfig.delimiter = rx.deli;
ESP_ERROR_CHECK(parlio_rx_soft_delimiter_start_stop(rx.unit, rx.deli, true));

gpio_set_level(RX_EN,1);      //使能FPGA的相关端口

// 启动接收事务
ESP_ERROR_CHECK(parlio_rx_unit_receive(rx.unit, rx.buffer, PARLIO_RX_PACKET_SIZE, &rx.receiveConfig));
return true;

}

void app_main(void)
{
printf("Begin rx test...\n");
printf("PARLIO_RX_PACKET_SIZE = %d\n",PARLIO_RX_PACKET_SIZE);

initOutputPins();
parlioReceive();   //第1次RX

int count = 0;

while (1) {
    printf("working!\n");
    vTaskDelay(1000 / portTICK_PERIOD_MS);

    if (rx.bufferFilled) {
        rx.bufferFilled = false;
        printf("%d rx transaction:\n",count++);
        for (int i=0;i<PARLIO_RX_PACKET_SIZE;i++){
            printf("%d,",rx.buffer[i]);
        }
        printf("\n");
    
        parlioReceive();  //第N次RX
    }
}

printf("End rx test.\n");

}
`

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions