Primer que nada, no se mucho de los dsPIC a pesar que tengo uno pero solo lo use para encender un led y nada mas ( un desperdicio), de todas formas voy a intentar ayudarte con lo que lea de los datasheet.
Lei que el oscilador que va a estar funcionando al momento del reset ( y tambien el contenido de OSCCON ) depende de los fuses, por lo que me imagino que si en los fuses pones que el oscilador primario es externo, que usas el PLL (si es que no modificas los valores del PLL, sino conviene que lo inicies sin PLL), deberias estar funcionando sin realizar un cambio de fuente de reloj(Solo del PLL si fuera necesario).
Lo unico que aconseja de comenzar con el interno es si el cristal se encuentra fuera del rango de 4 a 8 Mhz, la otra que me pregunto es si tenes habilitado el switching en los fuses. En fin si configuras para tener como reloj primario el XT y esta en rango, solo deberias tener en cuenta el PLL.
Si aun asi insistis por usar el interno como arranque + switch (no me refiero al IESO, sino poner como primario al reloj interno y luego cambiarlo) deberias hacer paso a paso lo que exige microchip que veo que hiciste hasta casi el final (Aunque por ahi varia el codigo).
Voy a suponer que tenes configurado el oscilador interno en los fuses y switch habilitado. Y el PLL deshabilitado para poder cambiar los valores del mismo.
//OSCCONH Unlock Sequence
__builtin_write_OSCCONH(0x78);
__builtin_write_OSCCONH(0x9A);
// Clock switching to incorporate PLL
__builtin_write_OSCCONH(0x01); // Initiate Clock Switch to Primary
//OSCCONL Unlock Sequence
__builtin_write_OSCCONL(0x46);
__builtin_write_OSCCONL(0x57);
// Oscillator with PLL (NOSC=0b011)
__builtin_write_OSCCONL(0x03); // Start clock switching
Veo estas poniendo un 0x01 en OSCCONH, es decir que el nuevo valor del oscilador ( NOSC ) es 0x01. Lo cual lo configuras como: 001 = Fast RC Oscillator with PLL (FRCPLL) , es decir el interno.
Pero luego.... te pones a preguntar por el nuevo valor ( Actual ) del oscilador y pretendes que sea otro valor es decir 0x3.
Cuando el cambio se realiza, NOSC pasa a COSC. Si ambos son iguales ( NOSC y COSC ) el cambio se aborta.
Otra de las cosas es que desde el PDF MPLAB® XC16 C Compiler User’s Guide
__builtin_write_OSCCONHAssembler Operator/
Machine Instruction*:
mov #0x78, w0
mov #0x9A, w1
mov #_OSCCON+1, w2
mov.b w0, [w2]
mov.b w1, [w2]
mov.b value, [w2]
Si te fijas en el ASM de esta instruccion este procede a escribir los valores para el unlock, y luego termina escribiendo el valor que le pones dentro al registro OSCCONx por lo tanto tu codigo se reduciria a:
//Aqui configuracion del PLL comenzando con el PLL desactivado
if(OSCCONbits.COSC!=0x3) //Pregunto si el actual oscilador es el externo si es el externo no tiene caso realizar el switching.
{
__builtin_write_OSCCONH(0x03); //Cargo 0x03 a OSCCONH = NOSC para el oscilador primario
__builtin_write_OSCCONL(0x01); // Cargo 0x01 a OSCCONL habilito el bit OSWEN para el cambio del clock
while (OSCCONbits.OSWEN); // Espero que se ponga en 0 para saber que se cambio
}
while (!OSCCONbits.LOCK); // Si es 0 que se quede en el loop
Codigo sacado leyendo la seccion de switch de:
dsPIC33F/PIC24H Family Reference Manual - Section 7. Oscillator - 7.11