本帖最后由 aozima 于 2021-6-15 12:55 编辑
我想使用CH579做一个网卡,SPI从机转以太网。
对芯片做了验证,基本上可行。现在遇到了2个问题。
1 SPI从机通过 COUNT=SPI0_DMA_NOW-SPI0_DMA_BEG,
在数据长度大于8字节时,无法获取传输长度。
实际传输大于8字节时,依然只显示7或8,但接收时内存中的数据是对的。
发送时,逻辑分析仪抓到的数据也是对的。
这点是否有解决办法?
没有的话,只能通过数据包头和校验来判定了。
不过芯片好像没有单独的硬件CRC,要用软件来算了。
另外吐槽下,就是SPI从机只能单双工,不过这也还能忍。
2 自己初始化以太网时,交换机灯不亮。
因为不需要在CH579里面跑协议栈,所以打算不要 CH57xNET.LIB
所以根据数据手册和 CH57xNET_LibInit 重写了以太网初始化。
但发现自己写的初始化,PHY好像没有工作,交换机的灯没有亮。
dump出PHY的寄存器发现有区别。
自己写的初始化代码如下
int ch57x_eth_init(const uint8_t *macaddr)
{
uint8_t tmp;
// 配置安全寄存器进入安全模式,打开以太网络的时钟和电源;
// 最好能关中断,因为只有16个周期有效果
R8_SAFE_ACCESS_SIG = 0x57;
R8_SAFE_ACCESS_SIG = 0xA8;
R8_SLP_CLK_OFF1 &= ~(1<<5); // 打开时钟
R8_SLP_POWER_CTRL &= ~(1<<1); // 打开电源
R8_SAFE_ACCESS_SIG = 0;
// 补充,建议这里做个反初始化,防止意外。
// 2 开启相应的中断,可选的,启用阻抗匹配电阻;
// R8_ETH_EIE = RB_ETH_EIE_RXERIE | RB_ETH_EIE_TXERIE | RB_ETH_EIE_R_EN50 | RB_ETH_EIE_TXIE | RB_ETH_EIE_LINKIE | RB_ETH_EIE_RXIE;
R8_ETH_EIE = 0; // 参考反汇编
tmp = R8_ETH_EIE; // 这里回读为0
PRINT("\r\n@%s L=%d, R8_ETH_EIE read out=%02X\r\n", __FUNCTION__, __LINE__, tmp);
tmp |= 0xdb; // 1101 1011 参考反汇编
R8_ETH_EIE = tmp; // 参考反汇编
tmp = R8_ETH_EIE; // 这里回读为 0xDB
PRINT("@%s L=%d, R8_ETH_EIE read out=%02X\r\n", __FUNCTION__, __LINE__, tmp);
tmp |= 4; // 0b100 50电阻 参考反汇编
R8_ETH_EIE = tmp; // 参考反汇编
tmp = R8_ETH_EIE; // 这里回读为 0xDF
PRINT("@%s L=%d, R8_ETH_EIE read out=%02X\r\n", __FUNCTION__, __LINE__, tmp);
R8_ETH_EIR = 0xFF; // 参考反汇编
tmp = R8_ETH_ESTAT;
tmp |= 0xC0; //清中断和buf中断
R8_ETH_ESTAT = tmp;// 参考反汇编写回
tmp = R8_ETH_ECON2;
// PRINT("@%s L=%d, R8_ETH_ECON2 read out=%02X\r\n", __FUNCTION__, __LINE__, tmp);
tmp >>= 4;
tmp <<= 4; // 清理低4位
R8_ETH_ECON2 = tmp;
tmp = R8_ETH_ECON2;
// PRINT("@%s L=%d, R8_ETH_ECON2 read out=%02X\r\n", __FUNCTION__, __LINE__, tmp);
tmp |= 4;
R8_ETH_ECON2 = tmp;
tmp = R8_ETH_ECON2;
// PRINT("@%s L=%d, R8_ETH_ECON2 read out=%02X\r\n", __FUNCTION__, __LINE__, tmp);
tmp = R8_ETH_ECON1;
PRINT("@%s L=%d, R8_ETH_ECON1 read out=%02X\r\n", __FUNCTION__, __LINE__, tmp);
tmp |= 0xC0; // 复位发送和接收模块
R8_ETH_ECON1 = tmp;
tmp = R8_ETH_ECON1;
PRINT("@%s L=%d, R8_ETH_ECON1 read out=%02X\r\n", __FUNCTION__, __LINE__, tmp);
//清高2位后,再写回
tmp &= 0x3F; // 取消复位状态
R8_ETH_ECON1 = tmp;
tmp = R8_ETH_ECON1;
PRINT("@%s L=%d, R8_ETH_ECON1 read out=%02X\r\n", __FUNCTION__, __LINE__, tmp);
R8_ETH_ERXFCON = 0;
tmp = R8_ETH_MACON1;
tmp |= 1; // MAC 接收使能
R8_ETH_MACON1 = tmp;
tmp = R8_ETH_MACON2;
tmp &= 0x1F; //清高3位后,再写回 RB_ETH_MACON2_PADCFG
R8_ETH_MACON2 = tmp;
tmp = R8_ETH_MACON2;
tmp |= 0x20; // 所有短包填充 0 至 60 字节,再 4字节 CRC;
R8_ETH_MACON2 = tmp;
tmp = R8_ETH_MACON2;
tmp |= 0x10; // 硬件填充 CRC
R8_ETH_MACON2 = tmp;
tmp = R8_ETH_MACON2;
tmp &= 0xfb; // 1111 1011 清除 巨型帧
R8_ETH_MACON2 = tmp;
tmp = R8_ETH_MACON2;
tmp |= 0x01; // 全双工
R8_ETH_MACON2 = tmp;
R16_ETH_MAMXFL = 0x24f; // 0x24f 1500 最大包长,需要确定
// 3 配置接收过滤模式、CRC 功能、MAC 地址;
// R8_ETH_ECON2 = 0x07; // 默认值 0x06,但读出来为4。
R32_ETH_HTL = 0x65820294;
R32_ETH_HTH = 0x220B1858;
// 设置MAC地址
// R32_ETH_MAADRL = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16) | (macaddr[3] << 24);
// R16_ETH_MAADRH = macaddr[4] | (macaddr[5] << 8);
{
uint8_t *ptr = (uint8_t *)&R32_ETH_MAADRL;
uint32_t value;
uint32_t i;
PRINT("mac ptr = %p\r\n", ptr);
for(i=0; i<6; i++)
{
tmp = *macaddr;
PRINT("mac #%d = %02X\r\n", i, tmp);
*ptr = tmp;
ptr++;
macaddr++;
}
value = R32_ETH_MAADRL;
PRINT("R32_ETH_MAADRL: 0x%08X\r\n", value);
value = R16_ETH_MAADRH;
PRINT("R16_ETH_MAADRH: 0x%04X\r\n", value);
}
// R32_ETH_MACON = 0x10310100; //直接用最终值,后面再做分解。
R8_ETH_ECON1 |= RB_ETH_ECON1_RXEN; // 收发控制,测试用
// 4 设置缓存;
R16_ETH_ERXST = (uint32_t)ch57x_rx_buf;
// 5 启动接收,开启中断。
R8_ETH_EIE |= RB_ETH_EIE_INTIE;
return 0;
}
|