Hi everybody,
I am trying to start some code after mqx has finished.
In other words, I want mqx to terminate and continue execution from a predefined address in RAM (where I loaded some code).
I modified the bsp and psp so that _mqx_exit is enabled.
Then I modified mqx_main.c like this:
int main
(
void
)
{ /* Body */
extern const MQX_INITIALIZATION_STRUCT MQX_init_struct;
/* Start MQX */
_mqx( (MQX_INITIALIZATION_STRUCT_PTR) &MQX_init_struct );
// mqx has terminated and is ready to run the loaded program
(*pFuncPointer)();
return 0;
} /* Endbody */
where pFuncPointer holds the address of the code to be run.
I do not expect this "function" to return.
In the debugger (CodeWarrior), I see that a brakpoint at pFuncPointer ist reached, but when I continue execution I stop in the idle task again and again.
I expected _mqx_exit to stop all tasks.
What do I need to do so I have only the code at pFuncPointer running?
Thanks and regards,
Martin
Solved! Go to Solution.
Hello martinpi,
can you share more code with us or at least detailed description which always helps to duplicate the behavior here on our side
We believe your application enables interrupts because during exiting from MQX, users' interrupt vectors are restored (_int_set_vector_table in int_vtab.c) and interrupts are disabled (. Do you enable INT?
I created small application with enabled interrupts after _mqx_exit() and it did not enter the Idle task. To further answer your question what does _mqx_exit do, first it executes _mqx_exit where int are disabled, invokes exit handler if there's any and then jump to the this code which is in mqx.c file also:
#if MQX_EXIT_ENABLED || MQX_CRIPPLED_EVALUATION
/* Setup a longjmp buffer using setjmp, so that if an error occurs
* in mqx initialization, we can perform a longjmp to this location.
*
* Also _mqx_exit will use this jumpbuffer to longjmp to here in order
* to cleanly exit MQX.
*/
if ( MQX_SETJMP( _mqx_exit_jump_buffer_internal ) ) {
_GET_KERNEL_DATA(kernel_data);
_int_set_vector_table(kernel_data->USERS_VBR);
return kernel_data->USERS_ERROR;
} /* Endif */
#endif
Regards,
MartinK
Hello martinpi,
have you read MQX reference manual about _mqx_exit function? Please read this NOTE:
"It is important to ensure that the environment (boot call stack) the MQX is
returning to is in the consistent state. This is not provided by distributed
MQX BSPs, because the boot stack is reused (rewritten) by MQX Kernel
data. Set the boot stack outside of Kernel data section to support correct
_mqx_exit functionality."
Regards,
MartinK
Yes, thank you, I did read that.
I compared the lcf to "Appendix C: linker command file (.lcf) in Code Warrior" in the document "Ethernet Bootloader for the MCU" and found the same values for bstack and end_of_kd. And, I think, this exactly what the bootloader should do: terminate and hand the control over.
Regards, Martin
Hello martinpi,
can you share more code with us or at least detailed description which always helps to duplicate the behavior here on our side
We believe your application enables interrupts because during exiting from MQX, users' interrupt vectors are restored (_int_set_vector_table in int_vtab.c) and interrupts are disabled (. Do you enable INT?
I created small application with enabled interrupts after _mqx_exit() and it did not enter the Idle task. To further answer your question what does _mqx_exit do, first it executes _mqx_exit where int are disabled, invokes exit handler if there's any and then jump to the this code which is in mqx.c file also:
#if MQX_EXIT_ENABLED || MQX_CRIPPLED_EVALUATION
/* Setup a longjmp buffer using setjmp, so that if an error occurs
* in mqx initialization, we can perform a longjmp to this location.
*
* Also _mqx_exit will use this jumpbuffer to longjmp to here in order
* to cleanly exit MQX.
*/
if ( MQX_SETJMP( _mqx_exit_jump_buffer_internal ) ) {
_GET_KERNEL_DATA(kernel_data);
_int_set_vector_table(kernel_data->USERS_VBR);
return kernel_data->USERS_ERROR;
} /* Endif */
#endif
Regards,
MartinK
Thank you for your answer and sorry for not anwering for so lang time. I had an influenza.
I started with the serial_to_telnet example for the K60F120 tower.
When I found that still get into the idle task, I tried to disable the interrupts befor entering the code to be executed.
(for some reasons I cannot paste code here, it looks somewhat like this:)
void (*pFuncPointer)() = 0;
in main (void)
{
extern const MQX_INITIALISATION_STRUCT MQX_init_struct;
mqx ( (MQX_INITIALISATION_STRUCT_PTR) &MQX_init_struct); //the normal mqx call
// now mqx has terminated and is ready to run the loaded program
if (pFuncPointer != 0)
{
_int_disable(); // just to see if I can prevent mqx from entering the idle task again
(*pFuncPointer)();
// should never reach this point here as pFuncPointer should contain a program with an infinite loop
}
return 0;
} // endbody
Regards, Martin