Tiempo entre palabras en SPI

5

Estoy intentando usar un dsPIC33F para generar una señal de datos que no debe interrumpirse entre palabras. Debe ser un tren continuo de 240 bits. Estoy cronometrando el SPI usando DMA con palabras de 16 bits, pero tengo espacios entre las palabras. ¿Hay algo que pueda hacer al respecto o me quedo con él?

¡Aquí está la cosa rara! Si lo hago usando una rutina de bucle que escribe continuamente en el registro SPI, ¡no hay huecos! Así que el DMA está creando estas brechas de alguna manera. Sería bueno si pudiera reducir el uso de la CPU con DMA, ya que el uso elevado de la CPU evita que se ejecuten otras tareas en segundo plano.

    
pregunta Thomas O

4 respuestas

2

Todavía no he usado el motor dsPIC DMA, pero esto me parece sorprendente. Cuando dices "escribir continuamente", ¿significa eso en un bucle esperando el indicador SPIxIF (o como se llame, no lo busques ahora)? Supongo que es la misma bandera que se usa para indicar al motor DMA que transfiera la siguiente palabra.

Si no está esperando SPIxIF, entonces simplemente está atascando los datos en el búfer SPI y los bits de salida no son predecibles. Quizás hay una brecha inherente entre las palabras. ¿Cuál es la velocidad de reloj SPI en términos de ciclos de instrucción por reloj?

SPI es inherentemente síncrono, por lo que una pequeña brecha no debería causar problemas. A menos que esté intentando usar el periférico SPI para otro que no sea SPI, su requisito no tiene sentido.

    
respondido por el Olin Lathrop
1

En el PIC18xx, el puerto SPI requiere un retraso entre el final de una palabra y el comienzo de la siguiente. IIRC, cuando ejecuta el puerto SPI a una velocidad de un bit por reloj de instrucciones, el intento de alimentar más de un byte por cada doce relojes de instrucción provocará un exceso de transmisión y pérdida de datos. Es bueno saber que no parece tener esa limitación en el dsPIC, pero supongo que el DMA no se activará hasta que el SPI esté vacío, lo que terminará imponiendo un retraso de un ciclo. No sé cómo funciona DMA en el dsPIC, pero en algunos procesadores es posible usar un temporizador para operar el DMA; tal vez podría intentar ejecutar DMA en el puerto SPI cada 16 ciclos; Si hay un retraso de un ciclo entre la escritura en el puerto y el inicio de la transferencia, la segunda señal del temporizador se producirá un ciclo antes de que el puerto SPI haya activado el segundo DMA. Una limitación de este enfoque es que, a menos que el puerto SPI tenga doble búfer, el DMA tendría que ejecutarse con la máxima prioridad. De lo contrario, si una transferencia se realizó con retraso, la próxima transferencia podría provocar un desbordamiento del búfer.

    
respondido por el supercat
1

En tu línea de exploración, interrumpe tu ubicación:

// Then write first DMA words. Successive words requested by SPI module.
// TODO: offset DMA by one word, or we will get duplicates. OR, just write
// a null word first... Whichever is easiest/best.
SPI2BUF = scanline_level_out_dma[0];
SPI1BUF = scanline_mask_out_dma[0];

Simplemente configure DMAxCONbits.FORCE = 1 antes de habilitar el canal DMA y forzará el primer byte tan pronto como el canal DMA esté habilitado.

También puede configurar sus canales de lectura ficticios en modo continuo (en lugar de un solo disparo) con un búfer de 1 palabra e iniciarlos cuando arranque e ignore la interrupción, no es necesario volver a pensar en ellos después de eso.

En su ejemplo de DMA todavía tiene interrupciones SPI definidas:

/**
 * _SPI1Interrupt: Primary ISR for SPI1.
 *
 * Only clears interrupt flag at the moment.
 */
void _MY_ISR _SPI1Interrupt()
{
        uint16_t nullread;
        nullread = SPI1BUF;
        nullread = SPI2BUF;
        IFS0bits.SPI1IF = 0;
}

Creo que esto aún se llama cuando DMA está habilitado a menos que deshabilites la interrupción de la CPU, es decir, tanto el controlador DMA como la CPU responden a la interrupción.

Esto parece repetir el trabajo del canal de lectura DMA y, además, es lento (solo use una variable global en lugar de una pila en un ISR como este). También puede estar bloqueando su transferencia, no sé realmente si el controlador DMA restablecería la interrupción mientras la CPU estaba en un controlador para esa interrupción.

  

¡Aquí está la cosa rara! Si lo hago   utilizando una rutina de bucle continuamente   escribiendo al registro SPI, hay   No hay huecos!

Esto es peligroso si no se comprueba SPIxIF, es muy posible que se esté confundiendo lo que sale y los bytes de prueba lo harían realmente difícil de encontrar.

EDITAR: Dado que su reloj SPI es aproximadamente 1/7 de su reloj de instrucciones, debe tener mucho cuidado en el controlador de interrupciones anterior para borrar SPI1IF ASAP o simplemente deshabilitarlo todo junto y dejar que Controlador DMA manejarlo. Para lograr un espacio sin interrupciones, tiene menos de 7 ciclos de instrucción para eliminar la siguiente palabra de la unidad SPI. Creo que tienes que deshabilitar completamente la intervención de la CPU y simplemente dejar que el controlador DMA se ocupe de él para tener alguna posibilidad, pero incluso entonces tienes 2 transferencias DMA y cualquier latencia de activación que haya desde el SPI - > DMA (su 1 reloj de instrucciones para SPIxIF para disparar, por ejemplo). Así que va a estar cerca.

    
respondido por el Mark
0

Simplemente configure DMAxCONbits.FORCE = 1 antes de habilitar el canal DMA y forzará el primer byte tan pronto como se habilite el canal DMA.

Estas dos líneas salvaron mis problemas de 2 días. Intenté una implementación de SPI basada en DMA en PIC32 MZ. Habia habilitado el Canal y luego Forcé un comienzo. En relojes SPI bajos de menos de 1 Mhz todo estaba bien. Una vez que probé más de 2 mhz (mi requerimiento es de 20 Mhz) comencé a repetir el primer personaje solo y el descanso estaba bien. Ahora que cambió el orden y probé que todo iba bien. Solo quería expresar mi agradecimiento.

    
respondido por el Seran Manian

Lea otras preguntas en las etiquetas