如何ESP32-S2 以太网SPI接口的CS建立时间?
- 问题现象:
偶尔出现_[0;31mE (6321) dm9051.mac: buffer size too small, needs 16444_[。只有降低SPI频率到20MHz才ok。
- 问题分析:
通过示波器测量,发现DM9051的cs建立时间和保持时间很紧张,其它信号质量和时序ok,需要增加cs的建立时间和保持时间来试试。
- 问题解决:
根据esp32-s2_technical_reference_manual_cn.pdf,
实际测试时发现spi_device_interface_config_t结构体.cs_ena_pretrans不能大于0,否则系统反复重启。
Spi_master.h文件spi_device_interface_config_t
uint16_t cs_ena_pretrans; ///< Amount of SPI bit-cycles the cs should be activated before the transmission (0-16). This only works on half-duplex transactions.
uint8_t cs_ena_posttrans; ///< Amount of SPI bit-cycles the cs should stay active after the transmission (0-16)
cs_ena_pretrans—确实有限制,是什么原因导致的?SPI总线接口本身是没有这个限制的,datasheet 说明DM9051的SPI可最高跑50MHz。
请问如何使能SPI_CS_SETUP,实现增加CS的建立时间? cs_ena_pretrans;--This only works on half-duplex transactions.
--看来驱动需要采用半双工,才能方便调整CS的建立时间。
SPI HOST可以全双工和半双工。
--DM9051
DM9051NP是可以支持半双工的,1字节+n字节数据。
但是目前DM9051是按全双工写的,估计是因为#ifdef CONFIG_IDF_TARGET_ESP32和#elif CONFIG_IDF_TARGET_ESP32S3在半双工有限制吧,按全双工设计兼容性更好。要是改成半双工工作量不小,还得仔细测试。
spi_master.c 对SPI传输的约束如下:
//check transmission length
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 || trans_desc->rxlength <= 32, "SPI_TRANS_USE_RXDATA only available for rxdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 || trans_desc->length <= 32, "SPI_TRANS_USE_TXDATA only available for txdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans_desc->length <= bus_attr->max_transfer_sz*8, "txdata transfer > host maximum", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans_desc->rxlength <= bus_attr->max_transfer_sz*8, "rxdata transfer > host maximum", ESP_ERR_INVALID_ARG);
SPI_CHECK(is_half_duplex || trans_desc->rxlength <= trans_desc->length, "rx length > tx length in full duplex mode", ESP_ERR_INVALID_ARG);
//check working mode
#if SOC_SPI_SUPPORT_OCT
SPI_CHECK(!(host->id == SPI3_HOST && trans_desc->flags & SPI_TRANS_MODE_OCT), "SPI3 does not support octal mode", ESP_ERR_INVALID_ARG);
SPI_CHECK(!((trans_desc->flags & SPI_TRANS_MODE_OCT) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "Incompatible when setting to both Octal mode and 3-wire-mode", ESP_ERR_INVALID_ARG);
SPI_CHECK(!((trans_desc->flags & SPI_TRANS_MODE_OCT) && !is_half_duplex), "Incompatible when setting to both Octal mode and half duplex mode", ESP_ERR_INVALID_ARG);
#endif
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "Incompatible when setting to both multi-line mode and 3-wire-mode", ESP_ERR_INVALID_ARG);
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && !is_half_duplex), "Incompatible when setting to both multi-line mode and half duplex mode", ESP_ERR_INVALID_ARG);
#ifdef CONFIG_IDF_TARGET_ESP32
SPI_CHECK(!is_half_duplex || !bus_attr->dma_enabled || !rx_enabled || !tx_enabled, "SPI half duplex mode does not support using DMA with both MOSI and MISO phases.", ESP_ERR_INVALID_ARG );
#elif CONFIG_IDF_TARGET_ESP32S3
SPI_CHECK(!is_half_duplex || !tx_enabled || !rx_enabled, "SPI half duplex mode is not supported when both MOSI and MISO phases are enabled.", ESP_ERR_INVALID_ARG);
#endif
//MOSI phase is skipped only when both tx_buffer and SPI_TRANS_USE_TXDATA are not set.
SPI_CHECK(trans_desc->length != 0 || !tx_enabled, "trans tx_buffer should be NULL and SPI_TRANS_USE_TXDATA should be cleared to skip MOSI phase.", ESP_ERR_INVALID_ARG);
//MISO phase is skipped only when both rx_buffer and SPI_TRANS_USE_RXDATA are not set.
//If set rxlength=0 in full_duplex mode, it will be automatically set to length
SPI_CHECK(!is_half_duplex || trans_desc->rxlength != 0 || !rx_enabled, "trans rx_buffer should be NULL and SPI_TRANS_USE_RXDATA should be cleared to skip MISO phase.", ESP_ERR_INVALID_ARG);
//In Full duplex mode, default rxlength to be the same as length, if not filled in.
// set rxlength to length is ok, even when rx buffer=NULL
if (trans_desc->rxlength==0 && !is_half_duplex) {
trans_desc->rxlength=trans_desc->length;
}
//Dummy phase is not available when both data out and in are enabled, regardless of FD or HD mode.
SPI_CHECK(!tx_enabled || !rx_enabled || !dummy_enabled || !extra_dummy_enabled, "Dummy phase is not available when both data out and in are enabled", ESP_ERR_INVALID_ARG);
考虑改成半双工工作量大,维持全双工,考虑mode3是建立时间更短,改成MODE 3,可以增加建立时间的余量10ns。hold时间cs_ena_posttrans=2可以增加不少。
.mode = 3,
.cs_ena_pretrans=0,
.cs_ena_posttrans=2,
还是维持20MHz,这样建立时间有25ns。
先测试稳定性如何,再适当提高频率。