-
Notifications
You must be signed in to change notification settings - Fork 16
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
Added support for CH390H, but needs further tests. (IDFGH-12291) #23
Conversation
393f7e9
to
f8171cf
Compare
Please refer https://github.com/espressif/esp-eth-drivers/blob/master/lan867x/idf_component.yml for the component manager. And please wait #24 be merged, then add it to |
@SergeyKharenko Overall, LGTM! |
Now |
@SergeyKharenko I would like to share some information of the progress at our side. Once we accept the PR to our repository, the "official" final responsibility for the component maintenance lays at our side (even though it would be great if you helped us with the maintenance even in the future). Therefore, we are currently in the process of developing and manufacturing a test board. Once ready, we run tests and continue with the PR review. Please stay tuned and thank you once again for your contribution. |
Thank you for your attention, it is a great pleasure for me. I will always keep an eye out for the follow-up work! |
Hi @SergeyKharenko, we have the test boards with CH390 in the office! I added the CH390 to
Could you please try to reproduce at your setup? Just add CH390 to https://github.com/espressif/esp-idf/blob/master/components/esp_eth/test_apps/main/esp_eth_test_common.c build and flash. The process is quite straight forward but if you needed any assistance, just let me know. |
I tried this modification, but it didn't work static esp_err_t emac_ch390_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint32_t length)
{
esp_err_t ret = ESP_OK;
emac_ch390_t *emac = __containerof(mac, emac_ch390_t, parent);
/* Check write address */
uint16_t tx_offset = 0;
/* Check if last transmit complete */
uint8_t tcr = 0;
ESP_GOTO_ON_FALSE(length <= ETH_MAX_PACKET_SIZE, ESP_ERR_INVALID_ARG, err,
TAG, "frame size is too big (actual %lu, maximum %u)", length, ETH_MAX_PACKET_SIZE);
int64_t wait_time = esp_timer_get_time();
do {
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_TCR, &tcr), err, TAG, "read TCR failed");
} while ((tcr & TCR_TXREQ) && ((esp_timer_get_time() - wait_time) < CH390_MAC_TX_WAIT_TIMEOUT_US));
if (tcr & TCR_TXREQ) {
ESP_LOGE(TAG, "last transmit still in progress, cannot send.");
return ESP_ERR_INVALID_STATE;
}
/* set tx length */
ESP_GOTO_ON_ERROR(ch390_register_write(emac, CH390_TXPLL, length & 0xFF), err, TAG, "write TXPLL failed");
ESP_GOTO_ON_ERROR(ch390_register_write(emac, CH390_TXPLH, (length >> 8) & 0xFF), err, TAG, "write TXPLH failed");
uint8_t mrrh = 0, mrrl = 0;
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_MWRH, &mrrh), err, TAG, "read MDRAH failed");
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_MWRL, &mrrl), err, TAG, "read MDRAL failed");
uint16_t addr_prev = mrrh << 8 | mrrl;
/* copy data to tx memory */
ESP_GOTO_ON_ERROR(ch390_memory_write(emac, buf, length), err, TAG, "write memory failed");
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_MWRH, &mrrh), err, TAG, "read MDRAH failed");
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_MWRL, &mrrl), err, TAG, "read MDRAL failed");
uint16_t addr_next = mrrh << 8 | mrrl;
tx_offset = (addr_prev <= addr_next) ? (addr_next - addr_prev) : (0x0C00 - addr_prev + addr_next);
ESP_GOTO_ON_FALSE(tx_offset == length, ESP_ERR_INVALID_STATE, err, TAG, "check tx data failed");
/* issue tx polling command */
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_TCR, &tcr), err, TAG, "read TCR failed");
ESP_GOTO_ON_ERROR(ch390_register_write(emac, CH390_TCR, tcr | TCR_TXREQ), err, TAG, "write TCR failed");
return ESP_OK;
err:
ESP_ERROR_CHECK_WITHOUT_ABORT(ch390_register_write(emac, CH390_MPTRCR, MPTRCR_RST_TX));
return ret;
}
static esp_err_t emac_ch390_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *length)
{
esp_err_t ret = ESP_OK;
emac_ch390_t *emac = __containerof(mac, emac_ch390_t, parent);
/* Check read address */
uint16_t rx_offset = 0;
uint8_t ready = 0;
/* dummy read, get the most updated data */
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_MRCMDX, &ready), err, TAG, "read MRCMDX failed");
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_MRCMDX, &ready), err, TAG, "read MRCMDX failed");
// if ready != 1 or 0 reset device
if (ready & CH390_PKT_ERR) {
emac_ch390_stop(mac);
esp_rom_delay_us(1000);
emac_ch390_start(mac);
ESP_LOGE(TAG, "PACK ERR");
} else {
__attribute__((aligned(4))) ch390_rx_header_t rx_header; // SPI driver needs the rx buffer 4 byte align
if (ready & CH390_PKT_RDY) {
ESP_GOTO_ON_ERROR(ch390_memory_read(emac, (uint8_t *) & (rx_header), sizeof(rx_header)), err, TAG, "peek rx header failed");
*length = (rx_header.length_high << 8) + rx_header.length_low;
ESP_GOTO_ON_FALSE(!((rx_header.status & 0xBF) || (*length > CH390_PKT_MAX)), ESP_ERR_INVALID_STATE, err, TAG, "check rx status failed");
uint8_t mrrh = 0, mrrl = 0;
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_MRRH, &mrrh), err, TAG, "read MDRAH failed");
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_MRRL, &mrrl), err, TAG, "read MDRAL failed");
uint16_t addr_prev = mrrh << 8 | mrrl;
/* copy rx memory to data */
ESP_GOTO_ON_ERROR(ch390_memory_read(emac, buf, *length), err, TAG, "read rx data failed");
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_MRRH, &mrrh), err, TAG, "read MDRAH failed");
ESP_GOTO_ON_ERROR(ch390_register_read(emac, CH390_MRRL, &mrrl), err, TAG, "read MDRAL failed");
uint16_t addr_next = mrrh << 8 | mrrl;
rx_offset = (addr_prev <= addr_next) ? (addr_next - addr_prev) : (0x3400 - addr_prev + addr_next);
ESP_GOTO_ON_FALSE(rx_offset == *length, ESP_ERR_INVALID_STATE, err, TAG, "check rx data failed");
// ESP_LOG_BUFFER_HEX(TAG, buf, rx_offset);
*length -= ETH_CRC_LEN;
} else {
*length = 0;
}
return ESP_OK;
}
err:
ESP_ERROR_CHECK_WITHOUT_ABORT(ch390_register_write(emac, CH390_MPTRCR, MPTRCR_RST_RX));
*length = 0;
return ret;
} does this indicate that the problem is not caused by a shift in the ch390 read/write register pointer? |
@ShunzDai, you tried to address the "start/stop" issue with your modification? Do I understand it correctly? |
yes |
@ShunzDai good to know it is reproducible issue. @SergeyKharenko we currently don't have any resources to investigate deeper. If you also don't have time to investigate, please state it as known issue in README. I would like to move forward with this PR. Please also address all the previous comments. |
@SergeyKharenko just a gentle reminder. Could you please have a look at the comments and address them so we could move forward? |
@SergeyKharenko great to having you back! Just two last comments:
|
@kostaond Certainly, I synced with the official repository and resolved the conflict. However the problem with the driver seems to be a bit more complicated than I thought... The only good news is that I'm heading into a week-long vacation, and it's a great time to deal with the problem! |
Do you mean |
@kostaond Yes, this issue bothered me a period. It's heartening that I've finally figured out the cause today!!! AnalysisKeyword: Dual TX Index; TX Pointer; Mysterious Compensation That is further corroborated in Chapter 8.4 of the Datasheet, which provides information about the TX Index(fig below). Through packet capture, it is found that whether it is an odd or even number of packets, the actual length transmitted is consistent with our set value, and there seems to be a mechanism of Mysterious Compensation inside the chip to ensure its correctness. Given the TX pointer position as The above pattern fails when the chip continuously transmitting corrupted DHCP messages(as @kostaond has mentioned). In this case, the actual position of the TX pointer is 2 bytes behind the theoretical position(348 actually while 350 in theory). For odd packets, the behavior is exactly the same as for the even packets mentioned earlier, so I guess that Index B is used when sending odd packets, and Index A is used for even packets, which is the opposite of the normal case. This also explains why the first two characters After reset, the chip uses the Index A initially. Here is the usage of the Index when the chip is normal (top) and when the issue occurs (bottom). At this point, the conjecture of the Mysterious Compensation has been conclusively verified! Looking at the entire start/stop loop, the only thing that comes to the operation directly on the TX pointer is
in SolutionQuite simple, two ways:
Test ResultA 100 loops ConclusionSometimes, a bug turns out to be the key to keeping the system running, and if it doesn't affect normal use, it may not be bad to leave it alone😁 PS: The code will be submitted over the next two days... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SergeyKharenko impressive job identifying root cause of the start/stop issue!
I performed the review and asked our intern to run the test_apps
with latest CH390 driver version since I'm a little bit busy with other things. Could you please also go over older comments and provide response how you addressed them? That would be great help for me. Thank you.
ethernet_init/examples/simple-ethernet/sdkconfig.defaults.ch390
Outdated
Show resolved
Hide resolved
@kostaond Almost all comments are replied to(try my best)~ |
@SergeyKharenko I finished the review. However, I cannot merge it due to conflicts. Please resolve. Please also squash the commits into one commit. |
bd4e845
to
acda86c
Compare
fix(ch390): length filter is not enabled build(ch390): lowered the IDF version requirement to 5.1 docs(ch390): change 10BASE-TX to 10BASE-T
acda86c
to
a223f6e
Compare
@kostaond Lack of experience with git manipulation led to many invalid pushes... After a period of autism, the problem was finally solved😀!!! I still divide all of the commits into two parts, initial publish and critical bug fix, which allows this issue to be documented on the timeline. |
@SergeyKharenko merged! Thank you for your patience and dedicated work! Your code has very high standard. Everything is very well structured and cleanly written. To be honest, I decided to update the |
Original PR: IDFGH-12259 and IDFGH-12264
Besides, two examples(iperf and tcp_server) have been added!