fix(ch390): deepen reset recovery

This commit is contained in:
2026-05-15 00:06:42 +08:00
parent 9ce1eed850
commit e1f4767e9a
5 changed files with 91 additions and 29 deletions
+38 -6
View File
@@ -13,6 +13,7 @@
#include "CH390_Interface.h"
#define CH390_PHY_BUSY_TIMEOUT_LOOPS 2000u
#define CH390_RX_READ_PTR_HIGH 0x0Cu
/**
* @name ch390_receive_packet
@@ -188,10 +189,36 @@ void ch390_write_eeprom(uint8_t reg, uint16_t value)
void ch390_software_reset()
{
ch390_write_reg(CH390_NCR, NCR_RST);
ch390_delay_us(10);
ch390_write_reg(CH390_NCR, 0);
ch390_write_reg(CH390_NCR, NCR_RST);
ch390_delay_us(10);
for (uint8_t i = 0u; i < 20u; ++i) {
ch390_delay_us(10u);
if ((ch390_read_reg(CH390_NCR) & NCR_RST) == 0u) {
break;
}
}
ch390_delay_us(1000u);
}
void ch390_reset_memory_pointers(void)
{
ch390_write_reg(CH390_MPTRCR, (uint8_t)(MPTRCR_RST_TX | MPTRCR_RST_RX));
for (uint8_t i = 0u; i < 20u; ++i) {
ch390_delay_us(1u);
if ((ch390_read_reg(CH390_MPTRCR) & (uint8_t)(MPTRCR_RST_TX | MPTRCR_RST_RX)) == 0u) {
break;
}
}
ch390_write_reg(CH390_MRRL, 0x00u);
ch390_write_reg(CH390_MRRH, CH390_RX_READ_PTR_HIGH);
}
void ch390_phy_power_cycle(void)
{
ch390_write_reg(CH390_IMR, IMR_NONE);
ch390_write_reg(CH390_RCR, 0x00u);
ch390_write_reg(CH390_GPR, (uint8_t)(ch390_read_reg(CH390_GPR) | GPR_PHYPD));
ch390_delay_us(50000u);
ch390_write_reg(CH390_GPR, (uint8_t)(ch390_read_reg(CH390_GPR) & (uint8_t)(~GPR_PHYPD)));
ch390_delay_us(100000u);
}
/**
@@ -209,6 +236,11 @@ void ch390_default_config()
// Multicast address hash table
uint8_t multicase_addr[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
ch390_write_reg(CH390_IMR, IMR_NONE);
ch390_write_reg(CH390_RCR, 0x00u);
ch390_write_reg(CH390_ISR, 0xFFu);
ch390_reset_memory_pointers();
ch390_set_phy_mode(CH390_AUTO);
ch390_write_reg(CH390_INTCR, (uint8_t)(INCR_TYPE_OD | INCR_POL_L));
// Clear status
@@ -220,8 +252,8 @@ void ch390_default_config()
// ch390_set_mac_address(mac_addr);
ch390_set_multicast(multicase_addr);
// Enable only the interrupts needed by the NO_SYS polling path.
ch390_write_reg(CH390_IMR, (uint8_t)(IMR_PRI | IMR_LNKCHGI | IMR_ROOI | IMR_ROI));
// Enable pointer auto-return and only the interrupts used by the NO_SYS polling path.
ch390_write_reg(CH390_IMR, (uint8_t)(IMR_PAR | IMR_PRI | IMR_LNKCHGI | IMR_ROOI | IMR_ROI));
// Enable RX with the reference receive filter.
ch390_write_reg(CH390_RCR, RCR_DIS_CRC | RCR_RXEN);
}