Tengo un problema interesante con el dsPIC33FJ128GP802 .
Lo tengo configurado como un dispositivo SPI esclavo conectado a un Arduino que actúa como maestro.
Timer1 está configurado para activar una interrupción en momentos específicos en una secuencia determinada.
Una de las secuencias de interrupciones tarda unos 50 µs en ejecutarse. Sí, sé que no es una "buena práctica" tener una rutina de interrupción que dure tanto tiempo, pero solo se usa una interrupción en el sistema, y las restricciones de tiempo significan que tiene que tomar ese tiempo.
Ahora, todo funciona: el SPI se está ejecutando y recibe comandos del Arduino. El Timer1 activa la interrupción en el momento justo y todo se ve bien.
Excepto que veo corrupción en el SPI. Solo puedo suponer que se debe a la interrupción del disparo del Timer1 durante la transferencia SPI. Si desactivo el temporizador y su interrupción, no tengo ningún problema con la transferencia SPI.
Por lo que entiendo de las interrupciones, se supone que todos los registros, etc., están exactamente en el mismo estado cuando el ISR regresa como estaban cuando se activó la interrupción. Eso es ciertamente lo que afirma el manual de usuario del C30.
Intenté volver a escribir mi código C para la recepción de SPI en ensamblador, pero el problema persiste.
Aquí hay un fragmento de mi código C:
while(PORTAbits.RA3==1); // Wait for a transfer to be requested
SPI1STATbits.SPIEN=1; // Enable the SPI module
SPI1BUF=0x0; // Prime the buffer to start a transfer
LATAbits.LATA1=0; // Signal to the master it may transfer
while(PORTAbits.RA3==0); // Wait for the master to signal it has transferred
in = SPI1BUF; // Store the resultant word
SPI1STATbits.SPIEN=0; // Turn off the SPI module
... perform operations depending on SPI command received ...
LATAbits.LATA1=1; // Signal to the master the command has finished and it may transfer again.
Ambos son activos-bajos.
Como puede ver, estoy usando más protocolo de enlace que el SPI normal, ya que necesito retroalimentación del esclavo al maestro cuando es seguro comenzar a transferir otro comando SPI.
Mi ISR se define como:
void __attribute__((__interrupt__,no_auto_psv)) _T1Interrupt(void)
He intentado agregar el __shadow__
atributo para usar los registros de sombra, pero no ha tenido efecto.
Entonces, ¿qué sucede realmente con el SPI en este chip cuando se activa una interrupción del temporizador? Como tiene un reloj independiente de la CPU principal, y solo cambia los bits dentro/fuera de un registro de desplazamiento, seguramente no debería verse afectado por las interrupciones.
Me está volviendo loco, por lo que cualquier sugerencia será bienvenida.
Normalmente configuraría el periférico SPI una vez y luego lo dejaría encendido. El apretón de manos adicional que está haciendo le impide usar el hardware a su máxima capacidad. También hacer una espera ocupada para que el maestro afirme la selección de esclavo es una mala idea si alguna vez desea que el procesador haga otra cosa.
Dado que está transfiriendo 16 bits menos por mensaje, dejaría que el hardware se encargara de ello. Luego puede monitorear el indicador de interrupción SPI para determinar cuándo se han recibido nuevos datos del maestro. Si necesita reducir la velocidad del maestro por razones de control de flujo, lo haría fuera del mensaje SPI. Sospecho que la interrupción está agregando latencia a su esquema de protocolo de enlace local, y algo en alguna parte no está del todo bien y no puede tolerar esa latencia. Eso suponiendo, por supuesto, que la interrupción no intente tocar el hardware SPI o cualquiera de sus líneas de E/S.
Majenko
Majenko
Majenko