Strange Software Reset Behavior on PIC24EP512GU810 using LPRC
I am adding a "very low speed" mode to my PIC24 which has been operating the main application for years, and I am seeing very strange software reset behavior when using LPRC as a main clock (to continuously run a long time doing some periodic housekeeping).
If I do a software reset without modifying the oscillators (using asm("reset")) I get the expected 0x43 RCON code when entering main(). When I switch to LPRC clock and reset, I get 0xC3, and when I reset the oscillator to it's primary speed and reset, I get 0x03. ox03 is problematic because I need to differentiate between power-on reset, and return from slow mode software reset. What's strange is even when I go back to the main oscillator configuration, I don't get the same results the second time as the first time.
The power supply is rock solid through these resets.
Looking for any hints or if anyone has any known bugs or workarounds:
Here's the code, run and reset at 3 different places (with the restart RCON codes in comments)
// Still running on main oscillator from ConfigureOscillator
// asm ("reset"); // Restarts the device (RCON code received 0x43))
ConfigureOscillatorLPRC();
#undef FCY
#define FCY (32768/2) // Reset the frequency so the delay macros work below this line
__delay_ms(100);
// asm ("reset"); // Restart the device (RCON code received 0xc3)
#undef FCY
#define FCY SYS_FREQ/2 // 60 MIPS at 120 MHz
ConfigureOscillator(); // Restore fast oscillator
__delay_ms(100);
asm("reset"); // Restart the device (RCON code received 0x03)
And here's the Oscillator configuration routines:void ConfigureOscillator(void)
{
_PLLPRE = 0; // 6MHZ/2 = 3MHZz
_PLLDIV = 78; // * 80 (78+2) = 240MHz
_PLLPOST = 0; // / 2 = 120 MHz (60 MIPS)
__builtin_write_OSCCONH(0x03); // Net new Clock Source to PLL
__builtin_write_OSCCONL(0x01); /* Start clock switching */
while(OSCCONbits.COSC != 0x3);
while(OSCCONbits.LOCK != 1);
// Configuring the auxiliary PLL, since the primary
// oscillator provides the source clock to the auxiliary
// PLL, the auxiliary oscillator is disabled. Note that
// the AUX PLL is enabled. The input 6MHz clock is divided
// by 2, multiplied by 24 and then divided by 1. Wait till
// the AUX PLL locks.
// 6MHz / 2 (pre) * 16 (M) / 1 (post) = 48 MHz
ACLKCON3bits.AOSCMD = 0; // Discable the Aux Xtal OSC
ACLKCON3bits.SELACLK = 1; // Aux clk comes from Aux PLL
ACLKCON3bits.ASRCSEL = 1; // Prmary Oscilator is SRC for Aux PLL
ACLKCON3bits.FRCSEL = 0; // Not using Fast RC for clock
ACLKCON3bits.APLLPRE = 1; // Divide input Osc by 2 (6MHz->3MHz)
ACLKDIV3 = 0x1; // Multiply by 16 (3 * 16 = 48MHz)
ACLKCON3bits.APLLPOST = 7; // Divide 48 MHz PLL OUtput by 1 for 48 MHz
ACLKCON3bits.ENAPLL = 1;
while(ACLKCON3bits.APLLCK != 1);
}
void ConfigureOscillatorLPRC(void)
{
/* Disable Watch Dog Timer */
RCONbits.SWDTEN = 0;
ACLKCON3bits.ENAPLL = 0; // Disable the auxiliary PLL
__builtin_write_OSCCONH(0x05); // Net new Clock Source to LPRC
__builtin_write_OSCCONL(0x01); /* Start clock switching */
while(OSCCONbits.COSC != 0x05);
}
post edited by dkark - 2021/01/24 05:29:01