본문 바로가기

RaspberryPi/RP2040

RP2040 Arduino IDE에서 SPI DMA 사용하기

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정도로 측정이 된다.

반응형