diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index 5728bd45e..2802dec17 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -177,7 +177,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus spihost[host]->dma_chan=dma_chan; if (dma_chan == 0) { - spihost[host]->max_transfer_sz = 32; + spihost[host]->max_transfer_sz = 64; } else { //See how many dma descriptors we need and allocate them int dma_desc_ct=(bus_config->max_transfer_sz+SPI_MAX_DMA_LEN-1)/SPI_MAX_DMA_LEN; @@ -213,6 +213,10 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus //Reset timing spihost[host]->hw->ctrl2.val=0; + //master use all 64 bytes of the buffer + spihost[host]->hw->user.usr_miso_highpart=0; + spihost[host]->hw->user.usr_mosi_highpart=0; + //Disable unneeded ints spihost[host]->hw->slave.rd_buf_done=0; spihost[host]->hw->slave.wr_buf_done=0; @@ -633,7 +637,6 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg) //Fill DMA descriptors int extra_dummy=0; if (trans_buf->buffer_to_rcv) { - host->hw->user.usr_miso_highpart=0; if (host->dma_chan == 0) { //No need to setup anything; we'll copy the result out of the work registers directly later. } else { @@ -662,16 +665,13 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg) //Use memcpy to get around alignment issues for txdata uint32_t word; memcpy(&word, &trans_buf->buffer_to_send[x/32], 4); - host->hw->data_buf[(x/32)+8]=word; + host->hw->data_buf[(x/32)]=word; } - host->hw->user.usr_mosi_highpart=1; } else { spicommon_dmaworkaround_transfer_active(host->dma_chan); //mark channel as active spicommon_setup_dma_desc_links(host->dmadesc_tx, (trans->length+7)/8, (uint8_t*)trans_buf->buffer_to_send, false); - host->hw->user.usr_mosi_highpart=0; host->hw->dma_out_link.addr=(int)(&host->dmadesc_tx[0]) & 0xFFFFF; host->hw->dma_out_link.start=1; - host->hw->user.usr_mosi_highpart=0; } } diff --git a/components/driver/test/test_spi_master.c b/components/driver/test/test_spi_master.c index 8887d5cef..8e245b526 100644 --- a/components/driver/test/test_spi_master.c +++ b/components/driver/test/test_spi_master.c @@ -234,6 +234,10 @@ TEST_CASE("SPI Master test", "[spi]") success &= spi_test(handle, 4); //aligned success &= spi_test(handle, 16); //small success &= spi_test(handle, 21); //small, unaligned + success &= spi_test(handle, 32); //small + success &= spi_test(handle, 47); //small, unaligned + success &= spi_test(handle, 63); //small + success &= spi_test(handle, 64); //small, unaligned destroy_spi_bus(handle); @@ -693,8 +697,22 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]") static const char MASTER_TAG[] = "test_master"; static const char SLAVE_TAG[] = "test_slave"; -DRAM_ATTR static uint8_t master_send[] = {0x93, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43}; -DRAM_ATTR static uint8_t slave_send[] = { 0xaa, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0 }; +DRAM_ATTR static uint8_t master_send[] = { + 0x93, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43, + 0x74, + 0x93, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43, + 0x74, + 0x93, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43, + 0x74, + }; +DRAM_ATTR static uint8_t slave_send[] = { + 0xaa, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0, + 0xda, + 0xaa, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0, + 0xda, + 0xaa, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0, + 0xda, + }; static void master_deinit(spi_device_handle_t spi) @@ -1006,6 +1024,8 @@ esp_err_t check_data(spi_transaction_t *t, spi_dup_t dup, slave_rxdata_t *slave_ return ESP_OK; } +int test_len[] = {1, 3, 5, 7, 9, 11, 33, 64}; + static void timing_init_transactions(spi_dup_t dup, timing_context_t* context) { spi_transaction_t* trans = context->master_trans; @@ -1014,7 +1034,7 @@ static void timing_init_transactions(spi_dup_t dup, timing_context_t* context) for (int i = 0; i < 8; i++ ) { trans[i] = (spi_transaction_t) { .flags = 0, - .rxlength = 8*(i*2+1), + .rxlength = 8*test_len[i], .rx_buffer = rx_buf_ptr, }; rx_buf_ptr += ((context->master_trans[i].rxlength + 31)/8)&(~3); @@ -1023,7 +1043,7 @@ static void timing_init_transactions(spi_dup_t dup, timing_context_t* context) for (int i = 0; i < 8; i++ ) { trans[i] = (spi_transaction_t) { .flags = 0, - .length = 8*(i*2+1), + .length = 8*test_len[i], .tx_buffer = master_send+i, }; } @@ -1031,7 +1051,7 @@ static void timing_init_transactions(spi_dup_t dup, timing_context_t* context) for (int i = 0; i < 8; i++ ) { trans[i] = (spi_transaction_t) { .flags = 0, - .length = 8*(i*2+1), + .length = 8*test_len[i], .tx_buffer = master_send+i, .rx_buffer = rx_buf_ptr, }; @@ -1042,7 +1062,7 @@ static void timing_init_transactions(spi_dup_t dup, timing_context_t* context) for (int i = 0; i < 8; i ++) { context->slave_trans[i] = (slave_txdata_t) { .start = slave_send + 4*(i%3), - .len = 256, + .len = 512, }; } } @@ -1073,7 +1093,7 @@ typedef struct { #define ESP_SPI_SLAVE_MAX_FREQ_SYNC SPI_MASTER_FREQ_40M -static test_timing_config_t timing_master_conf_t[] = {/**/ +static test_timing_config_t timing_master_conf_t[] = { { .cfg_name = "FULL_DUP, MASTER IOMUX", .freq_limit = SPI_MASTER_FREQ_13M, .dup = FULL_DUPLEX, diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index 26c3933cb..e836c1be4 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -217,7 +217,7 @@ speed a lot if small transactions are used. 2. When the DMA is enabled, it needs about 2us per transaction to setup the linked list. When the master is transferring, it automatically read data from the linked list. If the DMA is not enabled, CPU has to write/read each byte to/from the FIFO by itself. Usually this is faster than 2us, but the - transaction length is limited to 32 bytes for both write and read. + transaction length is limited to 64 bytes for both write and read. Typical transaction interval with one byte data is as below: @@ -401,7 +401,7 @@ Known Issues 2. disable the DMA by setting the last parameter to 0 in bus initialization function just as below: ``ret=spi_bus_initialize(VSPI_HOST, &buscfg, 0);`` - this may prohibit you from transmitting and receiving data longer than 32 bytes. + this may prohibit you from transmitting and receiving data longer than 64 bytes. 3. try to use command and address field to replace the write phase. 2. Full duplex mode is not compatible with the *dummy bit workaround*, hence the frequency is limited. See :ref:`dummy