Chronologist
Member
Greetiungs fellow programmers.
I encountered a problem, while trying to hook a DMA channel to an SPI DMA request on a Teensy 3.1 board. The program below is supposed to work in the following way:
Probably not the command itself is the problem, but rather some other configuration I missed. The problem is, upon inseting this line into the code, the device stops serial communication, so I can't really start debugging. It's the first time I've dealt with this kind of technology in microcontrollers, so I would not be surprised if I oversaw or misunderstood some aspects.
I would be very grateful for any support or ideas on the issue.
Thanks in advance and have a nice day,
Chrono.
I encountered a problem, while trying to hook a DMA channel to an SPI DMA request on a Teensy 3.1 board. The program below is supposed to work in the following way:
- On falling edge on the MISO pin, clock out 4 8-bit frames
- Each time data is read into the RX FIFO make a DMA request
- The DMA should move the frame from the top of the FIFO to the next buffer entry (buf)
- Repeat until the end of the buffer is reached
- Start overwriting buffer entries from the beginning
Code:
DMAMUX0_CHCFG0 = DMAMUX_SOURCE_SPI0_RX | DMAMUX_ENABLE;
I would be very grateful for any support or ideas on the issue.
Thanks in advance and have a nice day,
Chrono.
Code:
const int bufSize = 1024; // buffer size for receive buffer
char buf[bufSize]; // receive buffer for async transfer
int bufEntrySize = sizeof(*buf); // size of one buf entry in bit
void portc_isr()
{
SPI0_MCR |= SPI_MCR_CLR_RXF; // clear spi0 rx fifo
for (int i = 0; i < 4; i++) // clock out 32 bit from slave
{
SPI0_SR |= SPI_SR_TCF; // clear spi0 transfer complete flag
SPI0_PUSHR = 0xFF; // send "don't care" byte
while (!(SPI0_SR & SPI_SR_TCF)); // wait for spi transfer to complete
}
PORTC_ISFR = (1 << 7); // clear portc7 interrupt flag
NVIC_CLEAR_PENDING(IRQ_PORTC); // clear portc pending interrupts
}
void setup()
{
// digital pin config
PORTC_PCR7 = PORT_PCR_MUX(2) | PORT_PCR_IRQC(10); // configure portc7 as miso and interrupt on falling edge
NVIC_ENABLE_IRQ(IRQ_PORTC); // enable portc interrupt
GPIOC_PDDR = (1 << 5); // make portc5 an input
PORTC_PCR5 = PORT_PCR_DSE | PORT_PCR_MUX(2); // configure portc5 as sin
// spi config
SIM_SCGC6 |= SIM_SCGC6_SPI0; // activate spi0 clock
SPI0_MCR = SPI_MCR_MSTR; // enter spi0 master mode
SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_DBR; // spi0 frame size 8 bit and double baud rate
SPI0_RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS; // enable drain rx fifo dma request
// dma config
SIM_SCGC7 |= SIM_SCGC7_DMA; // enable dma clock
SIM_SCGC6 |= SIM_SCGC6_DMAMUX; // enable dmamux clock
DMAMUX0_CHCFG0 = DMAMUX_DISABLE; // disable dmamux
DMA_CR = 0; // use default settings
DMA_TCD0_SADDR = &SPI0_POPR; // set dma source to spi pop rx fifo register
DMA_TCD0_SOFF = 0; // don't increment source pointer
DMA_TCD0_ATTR = DMA_TCD_ATTR_SSIZE(DMA_TCD_ATTR_SIZE_8BIT) | // source data size is 8 bit
DMA_TCD_ATTR_DSIZE(DMA_TCD_ATTR_SIZE_8BIT); // destination data size is 8 bit
DMA_TCD0_NBYTES_MLNO = 1; // transfer one byte per request
DMA_TCD0_SLAST = 0; // don't change source pointer after major loop
DMA_TCD0_DADDR = buf; // set destination address to buffer
DMA_TCD0_DOFF = bufEntrySize; // increment destination pointer by 8 bit each time
DMA_TCD0_BITER_ELINKNO = DMA_TCD0_CITER_ELINKNO = bufSize; // do buf size major iterations
DMA_TCD0_DLASTSGA = -sizeof(buf); // return to beginning of buf after major loop finished
DMA_TCD0_CSR = DMA_TCD_CSR_DREQ; // clear request once served
DMAMUX0_CHCFG0 = DMAMUX_SOURCE_SPI0_RX | DMAMUX_ENABLE; // set spi0 as source of dma requests and enable mux
DMA_SERQ = DMA_SERQ_SERQ(0); // enable requests for channel 0
}
void loop()
{
}
Last edited: