Duet3D / RepRapFirmware

OO C++ RepRap Firmware
GNU General Public License v3.0
942 stars 534 forks source link

Use DMAC controller on SAM3X8E #110

Closed MarcoAntonini closed 7 years ago

MarcoAntonini commented 7 years ago

Hi David, I tried to enable DMAC controllers in the SAM3X8E processor, in order to connect at high speed hsmci and ESP SPI wifi module (like to DuetWifi) . When the DMAC controller is initialized in SetupSpi function I get a firmware crash and watchdog reset it. You tried to enable DMAC controller in 3X8E processor? Some advice?

#if USE_DMAC
    pmc_enable_periph_clk(ID_DMAC);
    dmac_init(DMAC);
    dmac_set_priority_mode(DMAC, DMAC_PRIORITY_ROUND_ROBIN);
    dmac_enable(DMAC);
    // The DMAC is master 4 and the SRAM is slave 0. Give the DMAC the highest priority.
    //matrix_set_slave_default_master_type(0, MATRIX_DEFMSTR_LAST_DEFAULT_MASTER);
    matrix_set_slave_priority(0, (3 << MATRIX_PRAS0_M4PR_Pos));
    // Set the slave slot cycle limit.
    // If we leave it at the default value of 511 clock cycles, we get transmit underruns due to the HSMCI using the bus for too long.
    // A value of 8 seems to work. I haven't tried other values yet.
    matrix_set_slave_slot_cycle(0, 8);
#endif

    // Set up the SPI pins
    ConfigurePin(g_APinDescription[APIN_SPI_SCK]);
    ConfigurePin(g_APinDescription[APIN_SPI_MOSI]);
    ConfigurePin(g_APinDescription[APIN_SPI_MISO]);
    ConfigurePin(g_APinDescription[APIN_SPI_SS0]);

    pmc_enable_periph_clk(ID_SPI0);
    spi_dma_disable();
    spi_reset(SPI0);                    // this clears the transmit and receive registers and puts the SPI into slave mode

#if USE_DMAC
    // Configure DMA RX channel
    dmac_channel_set_configuration(DMAC, CONF_SPI_DMAC_RX_CH,
            DMAC_CFG_SRC_PER(DMA_HW_ID_SPI_RX) | DMAC_CFG_SRC_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ASAP_CFG);

    // Configure DMA TX channel
    dmac_channel_set_configuration(DMAC, CONF_SPI_DMAC_TX_CH,
            DMAC_CFG_DST_PER(DMA_HW_ID_SPI_TX) | DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ASAP_CFG);
#endif

    (void)SPI0->SPI_SR;             // clear any pending interrupt
    SPI0->SPI_IDR = SPI_IER_NSSR;   // disable the interrupt

    NVIC_SetPriority(SPI0_IRQn, NvicPrioritySpi);
    NVIC_EnableIRQ(SPI0_IRQn);
dc42 commented 7 years ago

Yes, it would be possible to use DMA to do SPI transfers to/from the SD card.. On the Duet it would provide no advantage, because the Duet uses the HSMCI interface to the built-in SD card, and that interface uses DMA already. On Alligator and RADDS I think the advantage would be small. RRF doesn't use a RTOS, so the processor has to wait for the SPI transfer to complete before is can do anything else other than service interrupts. On the Duets, we use a callback function in the HSMCI driver to process network traffic while waiting for DMA to complete, and that speeds up file uploads a little. But SPI transfers are 40x slower than HSMCI, so I don't think that doing network operations during SPI transfers would speed up file upload significantly.

Two observations:

  1. RRF runs the SD card SPI interface at quite a slow clock rate - AFAIR it is 4MHz. We chose this to allow longer cable lengths to the external SD card, because file upload speed to the external SD card isn't a concern for us. For Alligator you might wish to use a higher SPI clock speed in order to get a higher file upload speed over the web interface.

  2. We will be switching RRF for the Duet WiFi/Ethernet to us a RTOS, which will make DMA more useful. However, I don't intend to use RTOS in the SAM3E builds because of the associated increased memory requirement.

MarcoAntonini commented 7 years ago

I've made some hardware fix on an Alligator test board, removed ethernet PHY and connected a HSMCI sdcard, so sdcard speed is no longer a problem. I released the SPI bus so it can communicate in slave mode with the ESP8266 module (as the Duet Wifi is doing). For this reason I am trying to enable DMA for communication with ESP8266 modules in SPI slave.

It's a good idea to use RTOS for RRF!

dc42 commented 7 years ago

On the Duet WiFi the hardware SPI channel is dedicated to the ESP8266 or the Ethernet adapter. The shared SPI subsystem in CoreNG for the Duet WiFi uses one of the USART channels instead. But if you don't need the shared SPI channel any more because you are using HSMCI for the SD card and you don't have any thermocouple or RTD interfaces, I think you should be able to disable the shared SPI subsystem completely, or move it to a spare USART channel, or to the second SPI channel on the SAM3X if the pins are free.

MarcoAntonini commented 7 years ago

Yes, I disabled the SharedSpi and reserved the hardware SPI only for network communication. I have successfully programmed ESP module from the SAM processor , great ESP module integration in RRF! Excellent job :) I can not understand my problem, when SAM processor is ready to receive data (in Network::SendCommand), SamTfrReadyPin is pulled high I get a processor crash and watchdog reset it. Thanks for the info, I do some hardware debugging to understand the problem..

dc42 commented 7 years ago

Which firmware did you install on the ESP? If your Alligator firmware is based on RRF1.19 then the WiFi firmware you need is built from project DuetWiFiSocketServer, not DuetWiFiServer. You can find a binary in the Release/DuetWiFi/Edge folder in my github repo. Also I suggest you update your main firmware source to my 1.19beta4 source code, because the earlier 1.19 releases have a bug that causes resets sometimes.

The Duet WiFi hardware uses a latch to remove the SamTfrReady signal from the ESP when the SAM starts the transfer. If you don't have that latch, you would need to make some firmware changes.

MarcoAntonini commented 7 years ago

Yes, the version is 1.19beta2 I've compiled the WifiSocketServer project and upload it in ESP module. I added the latch to remove SamTfr signal, so I'm sure I have the same code to work.
I'll try with beta4 version and pre-build WifiSocketServer.