RaspberryPi/RP2040

RP2040 Arduino IDE에서 SPI DMA 사용하기

nexp 2021. 5. 2. 08:41

Arduino IDE 개발환에서 RP2040의 SPI 전송률 테스트 하면 데이터 전송 간격이 1.2us 정도로 측정 된다.(RP2040 SPI테스트 참고)

 

 

고속의 데이터 전송을 위해서는 DMA가 필요한데 RP2040에서 SPI DMA 테스트를 진행 해 보자.

 

 

DMA 초기화 함수

#include "hardware/dma.h"
  int32_t            dma_tx_channel;
dma_channel_config dma_tx_config;
#define SPI_X spi0
bool initDMA(bool ctrl_cs)
{
  //ctrl_cs = ctrl_cs; // stop unused parameter warning
  dma_tx_channel = dma_claim_unused_channel(false);
  
  if (dma_tx_channel < 0) return false;
  dma_tx_config = dma_channel_get_default_config(dma_tx_channel);
  channel_config_set_transfer_data_size(&dma_tx_config, DMA_SIZE_8);

  channel_config_set_dreq(&dma_tx_config, spi_get_index(SPI_X) ? DREQ_SPI1_TX : DREQ_SPI0_TX);

  //DMA_Enabled = true;
  return true;
}

 

 

RP2040 SPI DMA 테스트 코드

void setup()
{
  Serial.begin(115200);
  Serial.println("RP2040 SPI DMA Test..");
  
  pinMode(PIN_OUT, OUTPUT);
  digitalWrite(PIN_OUT, 1);
  delay(2000);

  SPI.begin();
  initDMA(1);
  SPI.beginTransaction(SPISettings(31250000, MSBFIRST, SPI_MODE0)); 
}

unsigned char buf[2] = {1,2};
void loop() {
  digitalWrite(PIN_OUT, 1);
  
  //SPI.transfer(buf, sizeof(buf));
  //SPI.transfer(buf, sizeof(buf));

  dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_X)->dr, (uint8_t*)buf, sizeof(buf), true);

  digitalWrite(PIN_OUT, 0);

  delay(10);
}

 

 

DMA를 사용하면 SPI 전송 간격이 90ns 정도로 10배 이상 빨라지는 것을 확인 할 수 있다.

 

DMA 전송시 지연시간을 측정해 보기 위해 dmaWait() 함수를 추가 하고 두번 전송하는 코드를 작성해 보자.

void dmaWait(void)
{
  while (dma_channel_is_busy(dma_tx_channel));
#if !defined (RP2040_PIO_INTERFACE)
  // For SPI must also wait for FIFO to flush and reset format
  while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {};
  hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS);
#endif
}

unsigned char buf[2] = {1,2};
void loop() {
  digitalWrite(PIN_OUT, 1);

  //SPI.transfer(buf, sizeof(buf));
  //SPI.transfer(buf, sizeof(buf));

  dmaWait();
  dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_X)->dr, (uint8_t*)buf, sizeof(buf), true);

  dmaWait();
  dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_X)->dr, (uint8_t*)buf, sizeof(buf), true);

  digitalWrite(PIN_OUT, 0);
  delay(10);
    
}

 

 

테스트 결과 DMA 전송간 지연시간도 500ns정도로 측정이 된다.

반응형