More on K22 and SPI with DMA

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

More on K22 and SPI with DMA

288 Views
JBM
Contributor IV

A week or so ago, I posted a simple project with SPI using DMA for a K22FN512VMP12 MCU.  I'm trying to get data out of a sensor using the the sensor's WHOAMI register.  The transmit was only working once.   Here's that thread.  Now I am trying to enable the receive side and again, no interrupts.  

This is on custom hardware and it works if I bit-bang the SPI.  I'm trying to move to DMA so I can have a faster interrupt driven implementation.

I configured the receive side with another DMA channel, configured it pretty much the same (same number of bytes, etc).  The only difference I can see is that the source and destination addresses are different for TX and RX which makes sense.  When remove the INTMAJOR bit from the TX and set it on the RX, no interrupts.  If I move it back, I get interrupts.  Is there something weird/different with RX?

When I set INTMAJOR on the receive side, the SPI module is transmitting.  I see clock, data (MISO and MOSI) and chip select with my scope and they look correct to me.

Thanks.

Here's the code - one file for simplicity.

 

/*
 */

#include <stdint.h>
#include <stdbool.h>

#include "MK22F51212.h"

/*
 * Macros
 */
#define SPI_PUSHR_CTAS_CTAR0		(0x0)

/*
 *
 */
#define EnableInterrupts __asm(" CPSIE i");
#define DisableInterrupts __asm(" CPSID i");

/*
 * Data array - WHOAMI register from sensor
 */
#define SENSOR_FRAME_READ_WHOAMI							(0x40000091)

#define SENSOR_TRANSMIT_READ_WHOAMI_COUNT	(8)

static uint32_t SENSOR_TRANSMIT_READ_WHOAMI[SENSOR_TRANSMIT_READ_WHOAMI_COUNT] =
{
	SPI_PUSHR_CONT_MASK | SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_PCS(1) | SPI_PUSHR_TXDATA((SENSOR_FRAME_READ_WHOAMI >> 24) & 0xFF),
	SPI_PUSHR_CONT_MASK | SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_PCS(1) | SPI_PUSHR_TXDATA((SENSOR_FRAME_READ_WHOAMI >> 16) & 0xFF),
	SPI_PUSHR_CONT_MASK | SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_PCS(1) | SPI_PUSHR_TXDATA((SENSOR_FRAME_READ_WHOAMI >>   & 0xFF),
	SPI_PUSHR_CONT_MASK | SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_PCS(1) | SPI_PUSHR_TXDATA((SENSOR_FRAME_READ_WHOAMI      ) & 0xFF),

	SPI_PUSHR_CONT_MASK | SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_PCS(1) | SPI_PUSHR_TXDATA((SENSOR_FRAME_READ_WHOAMI >> 24) & 0xFF),
	SPI_PUSHR_CONT_MASK | SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_PCS(1) | SPI_PUSHR_TXDATA((SENSOR_FRAME_READ_WHOAMI >> 16) & 0xFF),
	SPI_PUSHR_CONT_MASK | SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_PCS(1) | SPI_PUSHR_TXDATA((SENSOR_FRAME_READ_WHOAMI >>   & 0xFF),
	SPI_PUSHR_EOQ_MASK  | SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_PCS(1) | SPI_PUSHR_TXDATA((SENSOR_FRAME_READ_WHOAMI      ) & 0xFF),
};

uint32_t receive_buffer[128];

/*
 * Transmit
 */
static void spi_transmit_receive(uint32_t* buffer, int count)
{
  SPI0->MCR = SPI_MCR_PCSIS(0x01) | SPI_MCR_MSTR_MASK | SPI_MCR_HALT_MASK;
  SPI0->SR  = SPI_SR_EOQF_MASK;

	DMA0->CR = 0x0;

	// Transmit
	DMAMUX->CHCFG[0] = DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(15);

	/* Set the Source and destination addresses */
	DMA0->TCD[0].SADDR = (uint32_t)buffer;
	DMA0->TCD[0].DADDR = (uint32_t)&SPI0->PUSHR;

	/* Source source and destination offsets */
	DMA0->TCD[0].SOFF = sizeof(uint32_t);
	DMA0->TCD[0].DOFF = 0;

	/* Modulo off and port sizes */
	DMA0->TCD[0].ATTR = DMA_ATTR_SSIZE(2) | DMA_ATTR_DSIZE(2);  // 2 = 32 bits

	/* Transfer size */
	DMA0->TCD[0].NBYTES_MLNO = 4;

	/* No link channel, transactions */
	DMA0->TCD[0].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(count);
	DMA0->TCD[0].BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(count);

	/* Adjustment to source and destination addresses */
	DMA0->TCD[0].SLAST = 0x0;
	DMA0->TCD[0].DLAST_SGA = 0x0;

#if 0
	DMA0->TCD[0].CSR = DMA_CSR_DREQ_MASK | DMA_CSR_INTMAJOR_MASK;
#else
	DMA0->TCD[0].CSR = DMA_CSR_DREQ_MASK;
#endif

	// Receive
	DMAMUX->CHCFG[1]  = DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(14);

	/* Set the Source and destination addresses */
	DMA0->TCD[1].SADDR = (uint32_t)&SPI0->POPR;
	DMA0->TCD[1].DADDR = (uint32_t)receive_buffer;

	/* Source source and destination offsets */
	DMA0->TCD[1].SOFF = 0;
	DMA0->TCD[1].DOFF = sizeof(uint32_t);

	/* Modulo off and port sizes */
	DMA0->TCD[1].ATTR = DMA_ATTR_SSIZE(2) | DMA_ATTR_DSIZE(2);  //source and destination size 0 = 8 bits, 2 = 32 bits

	/* Transfer size */
	DMA0->TCD[1].NBYTES_MLNO = 4;

	/* No link channel, transactions */
	DMA0->TCD[1].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(count);
	DMA0->TCD[1].BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(count);

	/* Adjustment to source and destination addresses */
	DMA0->TCD[1].SLAST = 0x0;
	DMA0->TCD[1].DLAST_SGA = 0x0;

#if 1
	DMA0->TCD[1].CSR = DMA_CSR_DREQ_MASK | DMA_CSR_INTMAJOR_MASK;
#else
	DMA0->TCD[1].CSR = DMA_CSR_DREQ_MASK;
#endif

  DMA0->ERQ = DMA_ERQ_ERQ0_MASK | DMA_ERQ_ERQ1_MASK;

  /*
   * Start the SPI -- now configured for DMA
   */
	SPI0->RSER |= SPI_RSER_TFFF_RE_MASK | SPI_RSER_TFFF_DIRS_MASK | SPI_RSER_RFDF_RE_MASK | SPI_RSER_RFDF_DIRS_MASK;
	SPI0->RSER |= SPI_RSER_EOQF_RE_MASK;
	SPI0->MCR  &= ~SPI_MCR_HALT_MASK;
}

/*
 *
 */
void PIT1_IRQHandler(void)
{
	if (PIT->CHANNEL[1].TFLG & PIT_TFLG_TIF_MASK)
	{
		spi_transmit_receive(SENSOR_TRANSMIT_READ_WHOAMI, SENSOR_TRANSMIT_READ_WHOAMI_COUNT);

		/* Clear interrupt flag */
		PIT->CHANNEL[1].TFLG = PIT_TFLG_TIF_MASK;
	}
}

void DMA0_IRQHandler(void)
{
	SPI0_SR   = SPI_SR_EOQF_MASK | SPI_SR_TCF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TFFF_MASK;
	DMA_CINT |= DMA_CINT_CAIR_MASK;
}

void DMA_Error_IRQHandler(void)
{
	__asm("nop");
}


/*
 * 		None
 */
static void pit_init(void)
{
	/* Start PIT module clock */
	SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;

  // Initialize timer
  PIT->MCR     				 	= PIT_MCR_FRZ_MASK;
  PIT->CHANNEL[1].LDVAL = 48000000UL/(2000UL);
  PIT->CHANNEL[1].TFLG  = PIT_TFLG_TIF_MASK;
  PIT->CHANNEL[1].TCTRL = PIT_TCTRL_TIE_MASK;

  /* Enable IRQ */
  NVIC_EnableIRQ(PIT1_IRQn);

  PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;
}

/*
 *
 */
static void ports_init(void)
{
	/* Clocking */
	SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK;

	/* Power for sensor */
	PORTC->PCR[5]	= PORT_PCR_MUX(1);
	PTC->PDDR = (1 << 5);
	PTC->PSOR = (1 << 5);

	/* Configure SPI ports */
	PORTD->PCR[0] = PORT_PCR_MUX(2);
	PORTD->PCR[1] = PORT_PCR_MUX(2);
	PORTD->PCR[2] = PORT_PCR_MUX(2);
	PORTD->PCR[3] = PORT_PCR_MUX(2);
}

/*
 *
 */
static void spi_dma_init(void)
{
	/* Clocking */
	SIM->SCGC6 |= SIM_SCGC6_SPI0_MASK;
	SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
	SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;

	/* Configure SPI */
	SPI0->MCR = SPI_MCR_HALT_MASK;
	SPI0->CTAR[0] = SPI_CTAR_FMSZ(7);
	SPI0->CTAR[1] = SPI_CTAR_FMSZ(7);

	NVIC_EnableIRQ(DMA0_IRQn);
}


/*
 *
 */
int main(void)
{
	EnableInterrupts;

	ports_init();
	spi_dma_init();
	pit_init();

	while (true)
	{
	}
	return 0;
}

 

 

0 Kudos
0 Replies