0

Feather M4 Express driving Adafruit TFT using DMA
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Feather M4 Express driving Adafruit TFT using DMA

by Brandon_Tarr on Thu Apr 29, 2021 12:11 am

I'm using an Adafruit 1.54" 240x240 TFT and driving it with a Feather M4 Express using the following code...

Code: Select all | TOGGLE FULL SIZE
#include <Arduino.h>
#include <Wire.h>
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ST7789.h"

#define TFT_CS      10
#define TFT_RST     9
#define TFT_DC      6

Adafruit_ST7789 tft = Adafruit_ST7789(&SPI, TFT_CS, TFT_DC, TFT_RST);

void setup(void) {
    Serial.begin(9600);
    while(!Serial);
    tft.init(240, 240);
    tft.fillScreen(ST77XX_BLACK);
    Serial.println("code never reaches this point with DMA enabled");
}

void loop() {
    while(1);
}


The code runs fine until I enable DMA in Adafruit_SPITFT. I've tracked the problem down to the Adafruit_SPITFT::writeColor() function. Specifically, the while (dma_busy) is in an endless loop because dma_callback() never fires. I'm not sure where to go from here as I'm pretty new to DMA. Thoughts?

Brandon_Tarr
 
Posts: 21
Joined: Tue Jul 08, 2014 8:48 am

Re: Feather M4 Express driving Adafruit TFT using DMA

by mikeysklar on Fri Apr 30, 2021 4:58 pm

From a comment in the Adafruit SPITFT library:

// If DMA is enabled, Arduino sketch MUST #include <Adafruit_ZeroDMA.h>


Have you tried adding the ZeroDMA include line?

mikeysklar
 
Posts: 4634
Joined: Mon Aug 01, 2016 8:10 pm

Re: Feather M4 Express driving Adafruit TFT using DMA

by Brandon_Tarr on Sat May 01, 2021 2:38 am

Yes. It doesn't make a difference. It is also already included near the top of Adafruit_SPITFT.cpp...

Code: Select all | TOGGLE FULL SIZE
#if defined(USE_SPI_DMA) && (defined(__SAMD51__) || defined(ARDUINO_SAMD_ZERO))
// #pragma message ("GFX DMA IS ENABLED. HIGHLY EXPERIMENTAL.")
#include "wiring_private.h" // pinPeripheral() function
#include <Adafruit_ZeroDMA.h>

Brandon_Tarr
 
Posts: 21
Joined: Tue Jul 08, 2014 8:48 am

Re: Feather M4 Express driving Adafruit TFT using DMA

by Brandon_Tarr on Sat May 01, 2021 3:42 am

I should also add that I have verified that DMA works with the hardware listed when I disable it in the library and do it manually via this...

Code: Select all | TOGGLE FULL SIZE
#include <Arduino.h>
#include <Wire.h>
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ST7789.h"
#include "Adafruit_ZeroDMA.h"

#define TFT_CS      10
#define TFT_RST     9
#define TFT_DC      6

static volatile bool dma_busy = false;
uint16_t dmaBuf[2][240];
uint8_t dmaIdx = 0;
DmacDescriptor *descriptor;
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
SPISettings settings(12000000, MSBFIRST, SPI_MODE0);
Adafruit_ZeroDMA  dma;

static void dma_callback(Adafruit_ZeroDMA *dma) {
  dma_busy = false;
}

void initDMA() {
    volatile uint32_t *data_reg;
    dma.allocate();
    dma.setTrigger(SERCOM1_DMAC_ID_TX);
    data_reg = &SERCOM1->SPI.DATA.reg;
    dma.setAction(DMA_TRIGGER_ACTON_BEAT);
    descriptor = dma.addDescriptor(NULL, (void *)data_reg, sizeof dmaBuf[0], DMA_BEAT_SIZE_BYTE, true, false);
    dma.setCallback(dma_callback);
}

void fillScreenBlackUsingDma() {
    uint16_t *dmaPtr;
    SPI.beginTransaction(settings);
    digitalWrite(TFT_CS, LOW);
    tft.setAddrWindow(0, 0, 240, 240);
    digitalWrite(TFT_CS, LOW);
    digitalWrite(TFT_DC, HIGH);

    for (uint8_t y = 0; y < 240; y++) {
        dmaPtr = &dmaBuf[dmaIdx][0];
        for (uint8_t x = 0; x < 240; x++) {
            *dmaPtr++ = (uint16_t)0x0000;
        }
        while(dma_busy);
        descriptor->SRCADDR.reg = (uint32_t)&dmaBuf[dmaIdx] + sizeof dmaBuf[0];
        dma_busy = true;
        dma.startJob();
        dmaIdx = 1 - dmaIdx;
    }
    while(dma_busy);
    digitalWrite(TFT_CS, HIGH);
    SPI.endTransaction();
}

void setup() {
    Serial.begin(9600);
    while(!Serial);
    tft.init(240, 240);
    initDMA();
    fillScreenBlackUsingDma();
    Serial.println("code reaches this point just fine using hand-rolled DMA");
}

void loop() {
    while(1);
}


As such, it appears there is a problem with the library code.

Brandon_Tarr
 
Posts: 21
Joined: Tue Jul 08, 2014 8:48 am

Re: Feather M4 Express driving Adafruit TFT using DMA

by mikeysklar on Mon May 03, 2021 2:27 pm

@Brandon_Tarr,

Thank you for the confirmation that you can still make DMA work by disabling it in the library. Would you like to open an issue here so this can get resolved?

https://github.com/adafruit/Adafruit-GFX-Library/issues

mikeysklar
 
Posts: 4634
Joined: Mon Aug 01, 2016 8:10 pm

Re: Feather M4 Express driving Adafruit TFT using DMA

by Brandon_Tarr on Mon May 03, 2021 4:35 pm

Will do. Thanks.

Brandon_Tarr
 
Posts: 21
Joined: Tue Jul 08, 2014 8:48 am

Please be positive and constructive with your questions and comments.