// Flush the receive buffer, in case we're out of sync
SPI0_MCR |= SPI_MCR_HALT;
SPI0_MCR |= SPI_MCR_CLR_RXF;
Basicamente detiene cualquier transferencia del SPI (TX,RX) y hace un flush de los buffer de Recepcion, limpiando tambien los contadores de cantidad de datos que poseen.
Pero si esta configurado como modo continuo entonces no hace nada.
Esto me tiene intrigado. Tengo un problema con la recepción de datos en mis pantallas Led, el caso es que a veces, de manera aleatoria la imagen se desplaza lateralmente y se queda ya desplazada.
Tiene que ser un problema del DMA, que es el que alimenta los datos por SPI. Sospecho que de vez en cuando entra algún pulso fantasma, tipo interferencia que hace que se lean los datos del buffer del DMA cuando no toca. Por SPI/DMA se reciben y cargan en una matriz interna, bloques de 128 bits (1 linea de la imagen), y después de cada carga de esos bits, en teoría se para el SPI, se borra su buffer, y se resetea el DMA para iniciar una nueva captura de datos (una nueva linea de la imagen).
Aún entrando de vez en cuando alguna interferencia, si cada vez que se reciben 128 bits en el buffer del DMA, correspondientes a los puntos de una linea de la pantalla, todo se borra y vuelta a empezar, no entiendo como la imagen se queda desplazada de manera continua.
Es como si el buffer del DMA se quedará con datos, no se si tiene que ver algo lo del "modo continuo" del DMA (¿ modo circular ?).
¿ Alguna idea, con el fuente que pongo bajo realmente se está vaciando todo, el buffer del SPI y el buffer del DMA ?
Configuración de SPI y DMA en el arranque del programa.
====================================
// Configura pines para SPI0
CORE_PIN10_CONFIG = PORT_PCR_MUX(2) | PORT_PCR_PE | PORT_PCR_PS;
// Activa reloj para SPI0
SIM_SCGC6 |= SIM_SCGC6_SPI0;
SPI0_MCR = SPI_MCR_HALT | SPI_MCR_MDIS | SPI_MCR_PCSIS(1<<0);
// Transferencia 16 bit, on rising edge
SPI0_CTAR0_SLAVE = SPI_CTAR_FMSZ(15);
// Enable FIFO Drain Request DMA
SPI0_RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS;
dmaSPI0rx = new DMAChannel();
dmaSPI0rx->source((volatile uint16_t&) SPI0_POPR);
dmaSPI0rx->destinationBuffer(plane_buffer, ROW_LENGTH * sizeof(uint16_t));
dmaSPI0rx->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_RX);
// Adjust isr priorities so SPI0 input preempts PORTB input NVIC_SET_PRIORITY(IRQ_PORTB, 32);
NVIC_SET_PRIORITY(IRQ_SPI0, 0);
NVIC_DISABLE_IRQ(IRQ_PORTB);
// Arranca SPI
SPI0_MCR &= ~SPI_MCR_HALT & ~SPI_MCR_MDIS;
digitalWriteFast(DMD_CS, LOW);
NVIC_ENABLE_IRQ(IRQ_PORTB);
dmaSPI0rx->enable();
Por una interrupción ligada a una señal de sincronismo externa, salta a una función para copiar los datos del buffer de DMA (128 bits, correspondientes a una linea de la imagen). En teoría, luego lo reinicia todo, el buffer del SPI y el buffer del DMA, previamente para ambos.
===============================================================
// Para SPI, y vacía el buffer RX FIFO
SPI0_MCR |= SPI_MCR_HALT; // Detiene el módulo SPI
SPI0_MCR |= SPI_MCR_CLR_RXF; // Borra el RX FIFO, manteniendo el SPI detenido.
// Resetea la transferencia del DMA
dmaSPI0rx->disable();
dmaSPI0rx->clearComplete();
dmaSPI0rx->destinationBuffer(plane_buffer, ROW_LENGTH * sizeof(uint16_t));
dmaSPI0rx->enable();
// Arranca SPI de nuevo
SPI0_MCR &= ~SPI_MCR_HALT; // Inicia el módulo SPI, para que se ejecute nuevamente
digitalWriteFast(DMD_CS, LOW);