I am using embOS for the Microchip PIC18LF46K22 (embOS_PIC18_MPLAB_C18_Src_V382o1).
The IDE is MPLAB-X v1.51. The compiler is C18 v3.38. The hardware is custom design.
In my application I need to change the PIC's system clock source from the internal oscillator to an external TCXO on the fly to perform some functions for a fixed period of time, then switch back to the internal clock source. The RTOS tick timing is running off of a separate secondary clock source (supplied through Timer 1) so the RTOS timing is not affected by the clock switching.
What I have found is that as soon as the RTOS does a task switch, the PIC clock somehow goes back to the internal clock source on its own without my application code changing it.
Here is a simplified code example:
void task_1()
{
while (1)
{
OSCCON = 0xE0; // Switch to external clock
while (0 == OSCCONbits.OSTS); // Wait for clock to stable
// start something ...
OS_Delay (100);
OSCCON = 0xE2; // Switch back to internal clock
while (1 == OSCCONbits.OSTS); // wait for clock to stabilize
// do something else ...
}
}
The PIC is switched to the external clock just before OS_Delay is called. It should stay on the external clock source for the duration of the delay, until software switches it back to the internal clock. However, as soon as the task switch occurs something other than the application code is changing the clock source (by modifying the OSCCON register) back to internal.
Fortunately we purchased the source code for the RTOS so I was able to single step through the OS_Delay function. I isolated the problem to the function OS_ChangeTask, which is in a file called OSKern.c. What I noticed is that only a task switch that go to the idle task triggered this problem. If it switches directly from one task to another task the system clock is fine.
So if I have a second task ...
void task_2()
{
while (1)
{
OS_Delay (50);
}
}
Switching from task_1 to task_2 is fine. The system clock stays external. But the other times when switching from task_1 to the idle task, this problem occurs. The idle task is just an infinite loop, so it should not change anything.
void OS_Idle(void)
{
while(1);
}
Has anyone else seen this behavior? Am I doing something wrong?
The IDE is MPLAB-X v1.51. The compiler is C18 v3.38. The hardware is custom design.
In my application I need to change the PIC's system clock source from the internal oscillator to an external TCXO on the fly to perform some functions for a fixed period of time, then switch back to the internal clock source. The RTOS tick timing is running off of a separate secondary clock source (supplied through Timer 1) so the RTOS timing is not affected by the clock switching.
What I have found is that as soon as the RTOS does a task switch, the PIC clock somehow goes back to the internal clock source on its own without my application code changing it.
Here is a simplified code example:
void task_1()
{
while (1)
{
OSCCON = 0xE0; // Switch to external clock
while (0 == OSCCONbits.OSTS); // Wait for clock to stable
// start something ...
OS_Delay (100);
OSCCON = 0xE2; // Switch back to internal clock
while (1 == OSCCONbits.OSTS); // wait for clock to stabilize
// do something else ...
}
}
The PIC is switched to the external clock just before OS_Delay is called. It should stay on the external clock source for the duration of the delay, until software switches it back to the internal clock. However, as soon as the task switch occurs something other than the application code is changing the clock source (by modifying the OSCCON register) back to internal.
Fortunately we purchased the source code for the RTOS so I was able to single step through the OS_Delay function. I isolated the problem to the function OS_ChangeTask, which is in a file called OSKern.c. What I noticed is that only a task switch that go to the idle task triggered this problem. If it switches directly from one task to another task the system clock is fine.
So if I have a second task ...
void task_2()
{
while (1)
{
OS_Delay (50);
}
}
Switching from task_1 to task_2 is fine. The system clock stays external. But the other times when switching from task_1 to the idle task, this problem occurs. The idle task is just an infinite loop, so it should not change anything.
void OS_Idle(void)
{
while(1);
}
Has anyone else seen this behavior? Am I doing something wrong?