ADC Data Recording with SpiSlave and DMA....

Status
Not open for further replies.

River_EE

Member
Hello,

I am trying to interface a Teensy4.0 and a ADC:AD7764 ADC. The ADC acts a spi master sending out 32bit data samples at 156KS/Sec.

I have it hooked up to the SPI interface on the TEENSY and am able to successfully read data at a slow (slower than 156KS/S rate) by manually reading the LPSPI4_RDR register. (16 samples are stored in the FIFO).

The issue is that I now what this process to be automatic so I can record ALL of the data and copy it over in large chunks. Setting up the DMA has been fun...

I expect the minor loop to run through 16 samples, then iterate the major loop (on the same channel). If I set CITER and BITER to 1 I successfully get 16 samples. If I set CITER and BITER to 2 I would expect to get 32 samples. Unfortunately, and strangely I only get 17 samples. Can anyone see what I didn't set up correctly?


Code:
Code:
#include <Arduino.h>

//Teensy4.1 Pin Declarations
const int SDO = 11;
const int SDI = 12;
const int SCO = 13;
const int nFSO = 10;
const int nFSI = 4;
const int nSYNC = 5;
const int OVERRANGE = 6;
const int nRESET = 7;
const int HEARTBEAT = 8;
const int ErrLED = 9;

//DMA Buffer
#define DMASIZE 100
uint32_t dmaDestination[DMASIZE];

//Functions
void configSpi();
void configDMA();
void startSPI();
void startDMA();
void startADC();
void printDMABUFFER();

void setup() 
{
	Serial.begin(115200);

  pinMode(nFSI, OUTPUT);
  pinMode(nSYNC, INPUT);
  pinMode(OVERRANGE, INPUT);
  pinMode(nRESET, OUTPUT);
  pinMode(HEARTBEAT, OUTPUT);
  pinMode(ErrLED, OUTPUT);
  
  digitalWrite(HEARTBEAT, HIGH);
  digitalWrite(ErrLED, HIGH);

  digitalWrite(nSYNC, HIGH);
  digitalWrite(SDI, LOW);
  digitalWrite(nFSI, HIGH);
  digitalWrite(nRESET, LOW);

  delay(1000);
  
  Serial.println("Preparing source and destination");
  memset(dmaDestination, 0x00, DMASIZE);
  Serial.println("DMA BUFFER: ........");
  printDMABUFFER();
  Serial.println("Buffers are Ready...");

  Serial.println("Starting ADC...");
  startADC();

  /** set up SPI **/
  Serial.println("Setting up, and starting SPI...");
	configSPI();
  startSPI();
  while((LPSPI4_FSR >> 16) < 16)
  {
    Serial.println("WAITING FOR FIFO TO FILL UP..,");
    delayMicroseconds(10);
  }
  Serial.println("Data Received"); 

  for(int i = 0; i<16; i++)
  {
    dmaDestination[i] = LPSPI4_RDR;
  }
  
  Serial.println("Data Copied"); 
  printDMABUFFER();
  
  Serial.println("Clearing buffer....");
  memset(dmaDestination, 0x00, DMASIZE);
  printDMABUFFER();
  
  Serial.println("Setting up DMA...");
  configDMA();
  startDMA();
  
  Serial.println("Starting DMA Transfer...");
  
  while(!(bool)(DMA_TCD1_CSR & 1<<7));
  
  Serial.println("DONE Transfer...");

  printDMABUFFER();
  Serial.print("Error Register: "); Serial.println(DMA_ES, BIN);
  

	
}

void loop() 
{            
  Serial.print("RXCOUNT: "); Serial.println(LPSPI4_FSR >> 16);
  if((LPSPI4_FSR >> 16)>15)
  {
    LPSPI4_CR |= LPSPI_CR_RRF; // reset SPI Registers
  }
  delayMicroseconds(1);
}

void configDMA()
{
  CCM_CCGR5 |= CCM_CCGR5_DMA(CCM_CCGR_ON);
  
  DMA_CR = DMA_CR_GRP0PRI | DMA_CR_EMLM | DMA_CR_CLM | DMA_CR_EDBG; //Group 1 Channel Priroty, Minor Loop Mapping, DEBUG Mode
  DMA_CERQ = 1; //Clear enable request for Channel 1
  DMA_CERR = 1; //Clear Errrir Register for channel 1
  DMA_CEEI = 1; //Clear enable error interrupt register for channel 1
  DMA_CINT = 1; //Clear Interupt Request Register channel 1
  
  DMA_ERQ = 1;
  DMA_TCD1_CITER = 5; //Set Major Iteration Count to 1
  DMA_TCD1_BITER = 5; //Set Starting MAjor Interation Count to 1
  DMA_TCD1_NBYTES = 64; //Tell it to transfer 16 bytes of data
  DMA_TCD1_SADDR = &LPSPI4_RDR; //Source Address
  DMA_TCD1_SOFF = 0; //Source Offset
  DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(DMA_TCD_ATTR_SIZE_32BIT) | DMA_TCD_ATTR_DSIZE(DMA_TCD_ATTR_SIZE_32BIT);
  DMA_TCD1_SLAST = -64; //put the source address back to the beginning when done. 
  DMA_TCD1_DADDR = &dmaDestination;//&dmaDestination;
  DMA_TCD1_DOFF = 4;
  DMA_TCD1_CITER_ELINKYES |= DMA_TCD_CITER_ELINK | DMA_TCD_CITER_ELINKYES_LINKCH(1);
  DMA_TCD1_BITER_ELINKYES |= DMA_TCD_CITER_ELINK | DMA_TCD_CITER_ELINKYES_LINKCH(1);
  DMA_TCD1_DLASTSGA = 0;
  //DMA_TCD1_CSR = DMA_TCD_CSR_INTMAJOR | DMA_TCD_CSR_DREQ;
  //DMA_TCD1_CSR = DMA_TCD_CSR_MAJORLINKCH(1) | DMA_TCD_CSR_MAJORELINK;
  DMAMUX_CHCFG1 = 0; //disable rxChannel
  //Serial.print("DMAMUX CHCFG1 Register: "); Serial.println(DMAMUX_CHCFG1);
  DMAMUX_CHCFG1 = DMAMUX_CHCFG_ENBL | DMAMUX_SOURCE_LPSPI4_RX; //Enable rxChannel    
  //Serial.print("DMAMUX CHCFG1 Register: "); Serial.println(DMAMUX_CHCFG1);
}


void startDMA()
{
  DMA_TCD1_CSR |= DMA_TCD_CSR_START;
}
  

// initialize LPSPI4
void configSPI()
{	
	CCM_CCGR1 |= CCM_CCGR1_LPSPI4(3);		// Turn on SPI clock	
	
  //MOSI - SDO Setup
	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02 = 3;						
	IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_02 = 0	| IOMUXC_PAD_DSE(0)	| IOMUXC_PAD_SPEED(3);
	IOMUXC_LPSPI4_SDO_SELECT_INPUT = 0;		

  //MISO - SDI Setup      
	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01 = 3;					
	IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_01 = 0	| IOMUXC_PAD_DSE(0)	| IOMUXC_PAD_SPEED(3);
	IOMUXC_LPSPI4_SDI_SELECT_INPUT = 0;			

  //SCK - SCO Setup
	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 3;				
	IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = 0	| IOMUXC_PAD_DSE(0)	| IOMUXC_PAD_SPEED(3);
  IOMUXC_LPSPI4_SCK_SELECT_INPUT = 0;  

  //CS - PCSO - FSO Setup
	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00 = 3;					
	IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_00 = 0  | IOMUXC_PAD_DSE(0)	| IOMUXC_PAD_SPEED(3);
  IOMUXC_LPSPI4_PCS0_SELECT_INPUT = 0;

	
	LPSPI4_CR &= ~LPSPI_CR_MEN;				// disable SPI
	LPSPI4_CR = 0	| LPSPI_CR_RST | LPSPI_CR_RTF	| LPSPI_CR_RRF;	// reset SPI Registers
	LPSPI4_CR = 0;							// turn off software reset															
  LPSPI4_CFGR1 = 0 | LPSPI_CFGR1_PINCFG(3);  //SOUT used for Input Data, SIN used for output data (Tested)
	LPSPI4_FCR = 0 | LPSPI_FCR_RXWATER(10) | LPSPI_FCR_RXWATER(5);							
	LPSPI4_TCR = 0 | LPSPI_TCR_FRAMESZ(31);				// use 31+1 bits (32-bits) per transfer
  LPSPI4_DER = LPSPI_DER_RDDE;							

}

void startADC()
{
  digitalWrite(nRESET, LOW);
  delay(1);
  digitalWrite(nRESET, HIGH);
  delay(2000);
}

void startSPI()
{
  LPSPI4_CR |= LPSPI_CR_MEN;        // ENABLE LPSPI4
}


void printDMABUFFER()
{
  for (int i = 0; i<DMASIZE; i++)
  {
    Serial.print(i);Serial.print(". ");Serial.print(dmaDestination[i] >> 8);Serial.print("\t");
  }
  Serial.println();
}


OUTPUT:

Preparing source and destination

DMA BUFFER: ........

0. 0 1. 0 2. 0 3. 0 4. 0 5. 0 6. 0 7. 0 8. 0 9. 0 10. 0 11. 0 12. 0 13. 0 14. 0 15. 0 16. 0 17. 0 18. 0 19. 0 20. 0 21. 0 22. 0 23. 0 24. 0 25. 0 26. 0 27. 0 28. 0 29. 0 30. 0 31. 0 32. 0 33. 0 34. 0 35. 0 36. 0 37. 0 38. 0 39. 0 40. 0 41. 0 42. 0 43. 0 44. 0 45. 0 46. 0 47. 0 48. 0 49. 0 50. 0 51. 0 52. 0 53. 0 54. 0 55. 0 56. 0 57. 0 58. 0 59. 0 60. 0 61. 0 62. 0 63. 0 64. 0 65. 0 66. 0 67. 0 68. 0 69. 0 70. 0 71. 0 72. 0 73. 0 74. 0 75. 0 76. 0 77. 0 78. 0 79. 0 80. 0 81. 0 82. 0 83. 0 84. 0 85. 0 86. 0 87. 0 88. 0 89. 0 90. 0 91. 0 92. 0 93. 0 94. 0 95. 0 96. 0 97. 0 98. 0 99. 0

Buffers are Ready...

Starting ADC...

Setting up, and starting SPI...

WAITING FOR FIFO TO FILL UP..,

WAITING FOR FIFO TO FILL UP..,

WAITING FOR FIFO TO FILL UP..,

WAITING FOR FIFO TO FILL UP..,

WAITING FOR FIFO TO FILL UP..,

WAITING FOR FIFO TO FILL UP..,

WAITING FOR FIFO TO FILL UP..,

WAITING FOR FIFO TO FILL UP..,

WAITING FOR FIFO TO FILL UP..,

WAITING FOR FIFO TO FILL UP..,

Data Received

Data Copied

0. 1579264 1. 1580576 2. 1573000 3. 1572928 4. 1580998 5. 1572880 6. 1580050 7. 1580160 8. 1580800 9. 1580556 10. 1572864 11. 1572878 12. 1579265 13. 1573132 14. 1572961 15. 1579076 16. 0 17. 0 18. 0 19. 0 20. 0 21. 0 22. 0 23. 0 24. 0 25. 0 26. 0 27. 0 28. 0 29. 0 30. 0 31. 0 32. 0 33. 0 34. 0 35. 0 36. 0 37. 0 38. 0 39. 0 40. 0 41. 0 42. 0 43. 0 44. 0 45. 0 46. 0 47. 0 48. 0 49. 0 50. 0 51. 0 52. 0 53. 0 54. 0 55. 0 56. 0 57. 0 58. 0 59. 0 60. 0 61. 0 62. 0 63. 0 64. 0 65. 0 66. 0 67. 0 68. 0 69. 0 70. 0 71. 0 72. 0 73. 0 74. 0 75. 0 76. 0 77. 0 78. 0 79. 0 80. 0 81. 0 82. 0 83. 0 84. 0 85. 0 86. 0 87. 0 88. 0 89. 0 90. 0 91. 0 92. 0 93. 0 94. 0 95. 0 96. 0 97. 0 98. 0 99. 0

Clearing buffer....

0. 0 1. 0 2. 0 3. 0 4. 0 5. 0 6. 0 7. 0 8. 0 9. 0 10. 0 11. 0 12. 0 13. 0 14. 0 15. 0 16. 0 17. 0 18. 0 19. 0 20. 0 21. 0 22. 0 23. 0 24. 0 25. 0 26. 0 27. 0 28. 0 29. 0 30. 0 31. 0 32. 0 33. 0 34. 0 35. 0 36. 0 37. 0 38. 0 39. 0 40. 0 41. 0 42. 0 43. 0 44. 0 45. 0 46. 0 47. 0 48. 0 49. 0 50. 0 51. 0 52. 0 53. 0 54. 0 55. 0 56. 0 57. 0 58. 0 59. 0 60. 0 61. 0 62. 0 63. 0 64. 0 65. 0 66. 0 67. 0 68. 0 69. 0 70. 0 71. 0 72. 0 73. 0 74. 0 75. 0 76. 0 77. 0 78. 0 79. 0 80. 0 81. 0 82. 0 83. 0 84. 0 85. 0 86. 0 87. 0 88. 0 89. 0 90. 0 91. 0 92. 0 93. 0 94. 0 95. 0 96. 0 97. 0 98. 0 99. 0

Setting up DMA...

Starting DMA Transfer...

DONE Transfer...

0. 1580544 1. 1572929 2. 1572928 3. 1580551 4. 1572896 5. 1573059 6. 1579056 7. 1580033 8. 1573007 9. 1580800 10. 1572912 11. 1572928 12. 1572866 13. 1581025 14. 1581055 15. 1572864 16. 1580620 17. 0 18. 0 19. 0 20. 0 21. 0 22. 0 23. 0 24. 0 25. 0 26. 0 27. 0 28. 0 29. 0 30. 0 31. 0 32. 0 33. 0 34. 0 35. 0 36. 0 37. 0 38. 0 39. 0 40. 0 41. 0 42. 0 43. 0 44. 0 45. 0 46. 0 47. 0 48. 0 49. 0 50. 0 51. 0 52. 0 53. 0 54. 0 55. 0 56. 0 57. 0 58. 0 59. 0 60. 0 61. 0 62. 0 63. 0 64. 0 65. 0 66. 0 67. 0 68. 0 69. 0 70. 0 71. 0 72. 0 73. 0 74. 0 75. 0 76. 0 77. 0 78. 0 79. 0 80. 0 81. 0 82. 0 83. 0 84. 0 85. 0 86. 0 87. 0 88. 0 89. 0 90. 0 91. 0 92. 0 93. 0 94. 0 95. 0 96. 0 97. 0 98. 0 99. 0

Error Register: 0

RXCOUNT: 12

RXCOUNT: 12

RXCOUNT: 12

RXCOUNT: 12

RXCOUNT: 13

RXCOUNT: 13

RXCOUNT: 13

RXCOUNT: 14

RXCOUNT: 14

RXCOUNT: 14

RXCOUNT: 14

RXCOUNT: 15

RXCOUNT: 15

RXCOUNT: 15

RXCOUNT: 15

RXCOUNT: 0

RXCOUNT: 0

RXCOUNT: 0

RXCOUNT: 1
 

Attachments

  • readADC4_DMA.ino
    5.6 KB · Views: 31
Status
Not open for further replies.
Back
Top