El cambio de reloj se bloquea al volver a la fuente original

Actualmente estoy trabajando en un proyecto donde el reloj necesita cambiar entre el oscilador primario con PLL (POSCPLL) al FRC y viceversa.

He inicializado el Reloj como PRIPLL usando los bits de configuración:

#pragma config FNOSC = PRIPLL
#pragma config POSCMOD = HS
#pragma config FPLLMUL = MUL_20
#pragma config FPLLIDIV = DIV_2
#pragma config FPLLODIV = DIV_1
#pragma config FPBDIV = DIV_1
#pragma config FCKSM = CSECME

que establece el OSCCON en 0x01453360 y da una señal de reloj de 80 MHz. Luego uso esta función para cambiar al FRC:

INTDisableInterrupts();
//Execute the System unlock sequence
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;

OSCCONbits.NOSC = 000;
OSCConfig(OSC_FRC, 0, 0, OSC_FRC_POST_1);
mOSCSetPBDIV(OSC_PB_DIV_1);
//Initiate the clock switch
OSCCONbits.OSWEN = 1;
//Lock SYSKEY
SYSKEY = 0x33333333;
int k = 0;
//Wait until OSWEN = 0 and switch is complete
while (OSCCONbits.OSWEN == 1){
    k++;
}
//Re-enable interrupts
INTEnableInterrupts();
SYSTEMConfig(GetStandbySystemClock(), SYS_CFG_ALL);

Para volver a POSC PLL, uso la misma estructura pero cambio el valor de NOSC a 011; y actualice OSCConfig a

OSCConfig(OSC_POSC_PLL, OSC_PLL_MULT_20, OSC_PLL_POST_1, 0); 

Que coincide con la secuencia en los bits de configuración pragma. Sin embargo, cuando lo ejecuto en el PIC32MX, el depurador en un PICKIT3 no puede pasar la función con estos bits de configuración, sin embargo, permitirá que se configure a la mitad de la velocidad (OSC_PLL_POST_2).

Sin embargo, si el depurador está en pausa, se puede ver que el OSCCON es el mismo, pero cuando se reanuda, el software se reinicia.

Si alguien pudiera decirme si me he perdido un bit de configuración para permitir volver al reloj inicial o si hay una mejor manera de hacerlo, ¡estaría extremadamente agradecido!

Información adicional: PIC32MX775F256L, placa personalizada, cristal de 8 MHz (FOXSDLF/080-20), el cristal se conecta a OSC1 y OSC2 (pin 63 y pin 64), cargando condensadores 22pF

gracias de antemano

EDITAR Ahora también he intentado configurar la nueva fuente de reloj sin usar la función OSCConfig y usando los valores duros en su lugar.

OSCCONbits.NOSC = 0b011;
OSCCONbits.PLLODIV = 0b000;
OSCCONbits.PLLMULT = 0b101;
OSCCONbits.PBDIV = 0b00;

Cuando PLLODIV es 0b000 pasa lo mismo, sin embargo cuando se pone a 0b001 funciona y el sistema va a media velocidad, ya que se divide por dos

EDITAR 2

Ahora he intentado cambiar entre relojes sin usar los bits de configuración #pragma que he eliminado

#pragma config FPLLMUL = MUL_20
#pragma config FPLLODIV = DIV_1
#pragma config FNOSC = PRIPLL
#pragma config FPBDIV = DIV_1

Utilizo las mismas funciones para configurar el reloj en primer lugar y obtengo el resultado deseado sin problemas. Luego cambio al reloj FRC, nuevamente sin problemas. Solo cuando trato de volver al reloj original encuentro un problema. Tampoco ayuda si primero cambio al mismo reloj con diferentes parámetros antes de volver a cambiar a los correctos a través del FRC nuevamente. Pero funcionará si primero cambio al reloj con diferentes parámetros, luego cambio al correcto a través del FRC al inicio.

Ahora tengo el código aislado para evitar que cualquier otro código afecte el cambio de reloj y todavía no hay diferencia.

Para el número decimal 10, la notación decimal es: 10, notación hexadecimal: 0xA, notación octal: 012. No hay notación binaria en C, pero una extensión común no estándar es 0b1010.

Respuestas (1)

Si tenía la intención de establecer esos bits como binarios, debe cambiar esto:

OSCCONbits.NOSC = 000;

a esto:

OSCCONbits.NOSC = 0b000;

Además, dondequiera que retroceda NOSC, debe establecerse 0b011no solo en 011.

Un prefijo de "0" en realidad hace que el valor sea octal en el compilador XC32 (como lo señaló @Lundin en los comentarios), que es decimal 9, que == 0b1001, por lo que este es ciertamente un problema que necesita solución.

Además, en la Guía de la biblioteca periférica PIC32 dice:

"En general, cuando se cambia a una frecuencia de reloj de CPU más alta, el divisor de bus periférico debe establecerse en el nuevo valor más bajo antes de cambiar la frecuencia de CPU"

Por lo tanto, al subir/bajar velocidades, debe usar el orden apropiado de las siguientes llamadas:

OSCConfig(OSC_FRC, 0, 0, OSC_FRC_POST_1);
mOSCSetPBDIV(OSC_PB_DIV_1);
Gracias, lo he agregado, pero no hay cambios en el resultado de mi problema. Parece que al cambiar el PLLODIV a 0b001 no se colgará, pero obviamente da la mitad de la velocidad. ¿Alguna idea de por qué se colgaría configurando PLLODIV en 0b000?
@MattWinstanley No puedo ver ningún problema obvio con eso en la hoja de datos. No es que el PICKit esté forzando un reinicio o algo estúpido, ¿verdad?
Ahora lo he probado con un programador ICD3 y otra vez cuando no está en modo depuración y vuelve a pasar lo mismo. Esta vez no se reinicia, pero MPLAB no le permitirá reanudar el programa. Probablemente sea algo ridículamente estúpido, ¡pero encontrar que cambiar un poco para que funcione está resultando cada vez más difícil!
@MattWinstanley Ver respuesta actualizada, ¿puede ser relevante?
Gracias, he intentado moverlo a todas las posiciones posibles pero no tuve suerte. Creo que mi próximo paso es intentar iniciar el oscilador usando un proceso similar al comienzo del código y evitar usar la configuración #pragma para ver si eso hace alguna diferencia. Solo en un enfoque de 'pruebe cualquier cosa y vea qué cambios' en este momento
011es octal (9 de diciembre), por lo que esta respuesta tiene algunos errores.
@Lundin Gracias, bien visto: actualicé mi respuesta, con crédito a su comentario.
@Lundin Entonces, si la hoja de datos dice que configure el bit NOSC en 011, ¿cuál es el valor correcto para configurarlo? deberian ser solo 3? La hoja de datos dice esto: bit 10-8 NOSC<2:0>: Nueva selección de oscilador bits 111 = Oscilador RC rápido interno (FRC) dividido por OSCCON<FRCDIV> bits 110 = Oscilador RC rápido interno (FRC) dividido por 16 101 = Oscilador interno de baja potencia RC (LPRC) 100 = Oscilador secundario (SOSC) 011 = Oscilador primario con módulo PLL (XTPLL, HSPLL o ECPLL) - Perdón por el espaciamiento horrendo
@MattWinstanley La hoja de datos obviamente usa notación binaria.
@RogerRowland Acabo de editar la pregunta con algunos casos de prueba más si tiene alguna idea.
@Lundin Actualicé los valores para leer 0b11 y también lo probé con 3 y ninguno hace ninguna diferencia. El compilador parece reconocer los comandos, ya que puede hacer el cambio inicialmente (ver edición 2), pero luego no puede volver al reloj con los parámetros que me gustaría usar.
@RogerRowland Gracias por toda su ayuda. Publicado allí ahora