fix(ch390): deepen reset recovery
This commit is contained in:
+38
-6
@@ -13,6 +13,7 @@
|
|||||||
#include "CH390_Interface.h"
|
#include "CH390_Interface.h"
|
||||||
|
|
||||||
#define CH390_PHY_BUSY_TIMEOUT_LOOPS 2000u
|
#define CH390_PHY_BUSY_TIMEOUT_LOOPS 2000u
|
||||||
|
#define CH390_RX_READ_PTR_HIGH 0x0Cu
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name ch390_receive_packet
|
* @name ch390_receive_packet
|
||||||
@@ -188,10 +189,36 @@ void ch390_write_eeprom(uint8_t reg, uint16_t value)
|
|||||||
void ch390_software_reset()
|
void ch390_software_reset()
|
||||||
{
|
{
|
||||||
ch390_write_reg(CH390_NCR, NCR_RST);
|
ch390_write_reg(CH390_NCR, NCR_RST);
|
||||||
ch390_delay_us(10);
|
for (uint8_t i = 0u; i < 20u; ++i) {
|
||||||
ch390_write_reg(CH390_NCR, 0);
|
ch390_delay_us(10u);
|
||||||
ch390_write_reg(CH390_NCR, NCR_RST);
|
if ((ch390_read_reg(CH390_NCR) & NCR_RST) == 0u) {
|
||||||
ch390_delay_us(10);
|
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
|
// Multicast address hash table
|
||||||
uint8_t multicase_addr[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
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_set_phy_mode(CH390_AUTO);
|
||||||
ch390_write_reg(CH390_INTCR, (uint8_t)(INCR_TYPE_OD | INCR_POL_L));
|
ch390_write_reg(CH390_INTCR, (uint8_t)(INCR_TYPE_OD | INCR_POL_L));
|
||||||
// Clear status
|
// Clear status
|
||||||
@@ -220,8 +252,8 @@ void ch390_default_config()
|
|||||||
// ch390_set_mac_address(mac_addr);
|
// ch390_set_mac_address(mac_addr);
|
||||||
ch390_set_multicast(multicase_addr);
|
ch390_set_multicast(multicase_addr);
|
||||||
|
|
||||||
// Enable only the interrupts needed by the NO_SYS polling path.
|
// Enable pointer auto-return and only the interrupts used by the NO_SYS polling path.
|
||||||
ch390_write_reg(CH390_IMR, (uint8_t)(IMR_PRI | IMR_LNKCHGI | IMR_ROOI | IMR_ROI));
|
ch390_write_reg(CH390_IMR, (uint8_t)(IMR_PAR | IMR_PRI | IMR_LNKCHGI | IMR_ROOI | IMR_ROI));
|
||||||
// Enable RX with the reference receive filter.
|
// Enable RX with the reference receive filter.
|
||||||
ch390_write_reg(CH390_RCR, RCR_DIS_CRC | RCR_RXEN);
|
ch390_write_reg(CH390_RCR, RCR_DIS_CRC | RCR_RXEN);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ enum ch390_phy_mode
|
|||||||
#define CH390_MAR 0x16
|
#define CH390_MAR 0x16
|
||||||
#define CH390_GPCR 0x1E
|
#define CH390_GPCR 0x1E
|
||||||
#define CH390_GPR 0x1F
|
#define CH390_GPR 0x1F
|
||||||
|
#define GPR_PHYPD (1<<0) // PHY power down
|
||||||
#define CH390_TRPAL 0x22
|
#define CH390_TRPAL 0x22
|
||||||
#define CH390_TRPAH 0x23
|
#define CH390_TRPAH 0x23
|
||||||
#define CH390_RWPAL 0x24
|
#define CH390_RWPAL 0x24
|
||||||
@@ -145,11 +146,14 @@ enum ch390_phy_mode
|
|||||||
#define INCR_POL_H 0x00
|
#define INCR_POL_H 0x00
|
||||||
#define CH390_ALNCR 0x4A
|
#define CH390_ALNCR 0x4A
|
||||||
#define CH390_SCCR 0x50
|
#define CH390_SCCR 0x50
|
||||||
|
#define SCCR_DIS_CLK (1<<0) // Stop internal clock
|
||||||
#define CH390_RSCCR 0x51
|
#define CH390_RSCCR 0x51
|
||||||
#define CH390_RLENCR 0x52
|
#define CH390_RLENCR 0x52
|
||||||
#define CH390_BCASTCR 0x53
|
#define CH390_BCASTCR 0x53
|
||||||
#define CH390_INTCKCR 0x54
|
#define CH390_INTCKCR 0x54
|
||||||
#define CH390_MPTRCR 0x55
|
#define CH390_MPTRCR 0x55
|
||||||
|
#define MPTRCR_RST_TX (1<<1) // Reset TX memory pointer
|
||||||
|
#define MPTRCR_RST_RX (1<<0) // Reset RX memory pointer
|
||||||
#define CH390_MLEDCR 0x57
|
#define CH390_MLEDCR 0x57
|
||||||
#define CH390_MRCMDX 0x70
|
#define CH390_MRCMDX 0x70
|
||||||
#define CH390_MRCMDX1 0x71
|
#define CH390_MRCMDX1 0x71
|
||||||
@@ -263,6 +267,7 @@ enum ch390_phy_mode
|
|||||||
#define CH390_MAR 0x16
|
#define CH390_MAR 0x16
|
||||||
#define CH390_GPCR 0x1E
|
#define CH390_GPCR 0x1E
|
||||||
#define CH390_GPR 0x1F
|
#define CH390_GPR 0x1F
|
||||||
|
#define GPR_PHYPD (1<<0) // PHY power down
|
||||||
#define CH390_TRPAL 0x22
|
#define CH390_TRPAL 0x22
|
||||||
#define CH390_TRPAH 0x23
|
#define CH390_TRPAH 0x23
|
||||||
#define CH390_RWPAL 0x24
|
#define CH390_RWPAL 0x24
|
||||||
@@ -298,10 +303,13 @@ enum ch390_phy_mode
|
|||||||
#define INCR_POL_L 0x01
|
#define INCR_POL_L 0x01
|
||||||
#define INCR_POL_H 0x00
|
#define INCR_POL_H 0x00
|
||||||
#define CH390_SCCR 0x50
|
#define CH390_SCCR 0x50
|
||||||
|
#define SCCR_DIS_CLK (1<<0) // Stop internal clock
|
||||||
#define CH390_RSCCR 0x51
|
#define CH390_RSCCR 0x51
|
||||||
#define CH390_RLENCR 0x52
|
#define CH390_RLENCR 0x52
|
||||||
#define CH390_BCASTCR 0x53
|
#define CH390_BCASTCR 0x53
|
||||||
#define CH390_MPTRCR 0x55
|
#define CH390_MPTRCR 0x55
|
||||||
|
#define MPTRCR_RST_TX (1<<1) // Reset TX memory pointer
|
||||||
|
#define MPTRCR_RST_RX (1<<0) // Reset RX memory pointer
|
||||||
#define CH390_MRCMDX 0xF0
|
#define CH390_MRCMDX 0xF0
|
||||||
#define CH390_MRCMDX1 0xF1
|
#define CH390_MRCMDX1 0xF1
|
||||||
#define CH390_MRCMD 0xF2
|
#define CH390_MRCMD 0xF2
|
||||||
@@ -424,6 +432,10 @@ void ch390_write_eeprom(uint8_t reg, uint16_t value);
|
|||||||
*/
|
*/
|
||||||
void ch390_software_reset(void);
|
void ch390_software_reset(void);
|
||||||
|
|
||||||
|
void ch390_reset_memory_pointers(void);
|
||||||
|
|
||||||
|
void ch390_phy_power_cycle(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name ch390_default_config
|
* @name ch390_default_config
|
||||||
* @brief Config CH390 with default options:
|
* @brief Config CH390 with default options:
|
||||||
|
|||||||
@@ -254,9 +254,9 @@ void ch390_hardware_reset(void)
|
|||||||
{
|
{
|
||||||
ch390_delay_us(10000); /* Short delay before reset */
|
ch390_delay_us(10000); /* Short delay before reset */
|
||||||
ch390_rst(0); /* Assert reset (low) */
|
ch390_rst(0); /* Assert reset (low) */
|
||||||
ch390_delay_us(3000); /* Hold reset for 3ms to satisfy datasheet minimum */
|
ch390_delay_us(50000); /* Recover chips stuck after repeated MCU resets */
|
||||||
ch390_rst(1); /* Release reset (high) */
|
ch390_rst(1); /* Release reset (high) */
|
||||||
ch390_delay_us(50000); /* Wait 50ms for CH390 to initialize reliably */
|
ch390_delay_us(500000); /* Allow EEPROM load, PHY, and SPI state to settle */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -329,6 +329,37 @@ static void ch390_runtime_refresh_diag(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ch390_runtime_recover_chip(struct netif *netif, const uint8_t *mac)
|
||||||
|
{
|
||||||
|
g_ch390_ready = 0u;
|
||||||
|
g_ch390_irq_pending = 0u;
|
||||||
|
|
||||||
|
ch390_hardware_reset();
|
||||||
|
if (ch390_runtime_probe_identity() == 0u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch390_software_reset();
|
||||||
|
if (ch390_runtime_probe_identity() == 0u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch390_phy_power_cycle();
|
||||||
|
ch390_default_config();
|
||||||
|
|
||||||
|
if (ch390_mac_address_valid(mac)) {
|
||||||
|
ch390_set_mac_address((uint8_t *)mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
ch390_runtime_prepare_netif(netif);
|
||||||
|
ch390_runtime_sync_mac(netif);
|
||||||
|
ch390_runtime_refresh_diag();
|
||||||
|
g_ch390_ready = g_diag.id_valid;
|
||||||
|
g_ch390_irq_pending = 0u;
|
||||||
|
|
||||||
|
return g_ch390_ready != 0u;
|
||||||
|
}
|
||||||
|
|
||||||
struct pbuf *ch390_runtime_input_frame(struct netif *netif)
|
struct pbuf *ch390_runtime_input_frame(struct netif *netif)
|
||||||
{
|
{
|
||||||
struct ethernetif *ethernetif = (struct ethernetif *)netif->state;
|
struct ethernetif *ethernetif = (struct ethernetif *)netif->state;
|
||||||
@@ -444,11 +475,8 @@ void ch390_runtime_init(struct netif *netif, const uint8_t *mac)
|
|||||||
ch390_gpio_init();
|
ch390_gpio_init();
|
||||||
SEGGER_RTT_WriteString(0, "ETH init: spi\r\n");
|
SEGGER_RTT_WriteString(0, "ETH init: spi\r\n");
|
||||||
ch390_spi_init();
|
ch390_spi_init();
|
||||||
SEGGER_RTT_WriteString(0, "ETH init: reset\r\n");
|
SEGGER_RTT_WriteString(0, "ETH init: deep reset\r\n");
|
||||||
ch390_hardware_reset();
|
g_ch390_ready = (uint8_t)ch390_runtime_recover_chip(netif, mac);
|
||||||
|
|
||||||
SEGGER_RTT_WriteString(0, "ETH init: probe\r\n");
|
|
||||||
g_ch390_ready = ch390_runtime_probe_identity();
|
|
||||||
if (g_ch390_ready == 0u) {
|
if (g_ch390_ready == 0u) {
|
||||||
ch390_runtime_prepare_netif(netif);
|
ch390_runtime_prepare_netif(netif);
|
||||||
netif_set_link_down(netif);
|
netif_set_link_down(netif);
|
||||||
@@ -456,11 +484,9 @@ void ch390_runtime_init(struct netif *netif, const uint8_t *mac)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SEGGER_RTT_WriteString(0, "ETH init: default\r\n");
|
|
||||||
ch390_default_config();
|
|
||||||
SEGGER_RTT_WriteString(0, "ETH init: mac\r\n");
|
SEGGER_RTT_WriteString(0, "ETH init: mac\r\n");
|
||||||
if (ch390_mac_address_valid(mac)) {
|
if (ch390_mac_address_valid(mac)) {
|
||||||
ch390_set_mac_address((uint8_t *)mac);
|
ch390_runtime_sync_mac(netif);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (mac != NULL) {
|
if (mac != NULL) {
|
||||||
@@ -660,15 +686,7 @@ bool ch390_runtime_emergency_reset(struct netif *netif)
|
|||||||
}
|
}
|
||||||
g_tx_consecutive_timeout = 0u;
|
g_tx_consecutive_timeout = 0u;
|
||||||
|
|
||||||
ch390_software_reset();
|
(void)ch390_runtime_recover_chip(netif, (netif != NULL) ? netif->hwaddr : NULL);
|
||||||
ch390_delay_us(5000u);
|
|
||||||
ch390_default_config();
|
|
||||||
ch390_runtime_prepare_netif(netif);
|
|
||||||
ch390_runtime_sync_mac(netif);
|
|
||||||
g_ch390_irq_pending = 0u;
|
|
||||||
|
|
||||||
ch390_runtime_refresh_diag();
|
|
||||||
g_ch390_ready = g_diag.id_valid;
|
|
||||||
|
|
||||||
if (g_ch390_ready == 0u) {
|
if (g_ch390_ready == 0u) {
|
||||||
SEGGER_RTT_WriteString(0, "ETH emergency reset: chip not responding\r\n");
|
SEGGER_RTT_WriteString(0, "ETH emergency reset: chip not responding\r\n");
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Code (inc. data) RO Data RW Data ZI Data Debug Object Name
|
Code (inc. data) RO Data RW Data ZI Data Debug Object Name
|
||||||
632 0 0 0 0 0 ch390.o
|
794 0 0 0 0 0 ch390.o
|
||||||
616 0 64 0 0 0 ch390_interface.o
|
618 0 64 0 0 0 ch390_interface.o
|
||||||
2546 0 85 6 136 0 ch390_runtime.o
|
2584 0 85 6 136 0 ch390_runtime.o
|
||||||
3958 0 591 8 1240 0 config.o
|
3958 0 591 8 1240 0 config.o
|
||||||
8 0 0 0 0 0 def.o
|
8 0 0 0 0 0 def.o
|
||||||
124 0 0 0 0 0 dma.o
|
124 0 0 0 0 0 dma.o
|
||||||
@@ -57,7 +57,7 @@ Memory Map of the image
|
|||||||
|
|
||||||
Load Region LR_IROM1
|
Load Region LR_IROM1
|
||||||
|
|
||||||
Execution Region ER_IROM1 (Exec base: 0x08000000, Size: 0x0000DED8, Max: 0x00010000, END)
|
Execution Region ER_IROM1 (Exec base: 0x08000000, Size: 0x0000DFA0, Max: 0x00010000, END)
|
||||||
|
|
||||||
Execution Region RW_IRAM1 (Exec base: 0x20000000, Size: 0x00004FD8, Max: 0x00005000, END)
|
Execution Region RW_IRAM1 (Exec base: 0x20000000, Size: 0x00004FD8, Max: 0x00005000, END)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user