How to use OS_ExtendTaskContext

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • How to use OS_ExtendTaskContext

    Hi,

    I'm using embOS 3.60 and just wanted to use OS_ExtendTaskContext() to save task specific global variables as described in the User guide.
    unfortunately it does not work as expected.
    As far as I can see the variables are not correctly stored on the stack or restored after the context is activated again.

    The functions for saving and restoring are just like the example with the small difference that I need to store 2 variables:

    Source Code

    1. typedef struct {
    2. OS_U32 VarA;
    3. OS_U32 VarB;
    4. } T_context_extention;
    5. ...
    6. OS_U32 _VarA;
    7. OS_U32 _VarB;
    8. ...
    9. static void _SaveConext(void * pStack)
    10. {
    11. T_context_extention* p;
    12. p =((T_context_extention*)pStack) - (1 - OS_STACK_AT_BOTTOM); /* create pointer */
    13. /* save all members of ther structure */
    14. p->VarA = _VarA;
    15. p->VarB = _VarB;
    16. }
    17. static void _RestoreContext(const void * pStack)
    18. {
    19. T_context_extention* p;
    20. p =((T_context_extention*)pStack) - (1 - OS_STACK_AT_BOTTOM); /* creat pointer */
    21. /* save all members of ther structure */
    22. _VarA = p->VarA;
    23. _VarB = p->VarB;
    24. }
    Display All


    As far as I can see VarA is stored correctly but VarB is not.
    So I start thinking about it and the point I don't get is: where exactly will be VarA and VarB stored on the stack?
    Is this the end of the stack or a fixed place in the beginning of the stack? And how does the OS know how many space I need there to store my extended context informations?
    Do I need to tell the OS somehow that there is more stack needed for the context extension?

    Kind Regards
    sowiso
  • Hi,

    which embOS (Compiler, CPU) do you use?

    I modified our sample application for extended task context (ExtendTaskContext.c) and added the two variables like you did.
    The application runs without any problem, the variables are correctly stored and restored.

    Here is the complete application code:

    C Source Code

    1. #include "RTOS.h"
    2. OS_STACKPTR int StackHP[128], StackLP[128]; /* Task stacks */
    3. OS_TASK TCBHP, TCBLP; /* Task-control-blocks */
    4. OS_U32 _VarA;
    5. OS_U32 _VarB;
    6. /*********************************************************************
    7. *
    8. * _Restore
    9. * _Save
    10. *
    11. * Function description
    12. * This function pair saves and restores an extended task context.
    13. * In this case, the extended task context consists of just a single
    14. * member, which is a global variable.
    15. */
    16. typedef struct {
    17. OS_U32 VarA;
    18. OS_U32 VarB;
    19. } CONTEXT_EXTENSION;
    20. static void _Save(void * pStack) {
    21. CONTEXT_EXTENSION * p;
    22. p = ((CONTEXT_EXTENSION*)pStack) - (1 - OS_STACK_AT_BOTTOM); // Create pointer to our structure
    23. //
    24. // Save all members of the structure
    25. //
    26. p->VarA = _VarA;
    27. p->VarB = _VarB;
    28. }
    29. static void _Restore(const void * pStack) {
    30. const CONTEXT_EXTENSION * p;
    31. p = ((const CONTEXT_EXTENSION *)pStack) - (1 - OS_STACK_AT_BOTTOM); // Create pointer to our structure
    32. //
    33. // Restore all members of the structure
    34. //
    35. _VarA = p->VarA;
    36. _VarB = p->VarB;
    37. }
    38. /*********************************************************************
    39. *
    40. * Global variable which holds the function pointers
    41. * to save and restore the task context.
    42. */
    43. const OS_EXTEND_TASK_CONTEXT _SaveRestore = {
    44. _Save,
    45. _Restore
    46. };
    47. /********************************************************************/
    48. /*********************************************************************
    49. *
    50. * HPTask
    51. *
    52. * Function description
    53. * During the execution of this function, the thread-specific
    54. * global variable has always the same value of 1.
    55. */
    56. static void HPTask(void) {
    57. OS_ExtendTaskContext(&_SaveRestore);
    58. _VarA = 1;
    59. _VarB = 2;
    60. while (1) {
    61. OS_Delay (10);
    62. }
    63. }
    64. /*********************************************************************
    65. *
    66. * LPTask
    67. *
    68. * Function description
    69. * During the execution of this function, the thread-specific
    70. * global variable has always the same value of 2.
    71. */
    72. static void LPTask(void) {
    73. OS_ExtendTaskContext(&_SaveRestore);
    74. _VarA = 3;
    75. _VarB = 4;
    76. while (1) {
    77. OS_Delay (50);
    78. }
    79. }
    80. /*********************************************************************
    81. *
    82. * main
    83. */
    84. int main(void) {
    85. OS_IncDI(); /* Initially disable interrupts */
    86. OS_InitKern(); /* Initialize OS */
    87. OS_InitHW(); /* Initialize Hardware for OS */
    88. /* You need to create at least one task here ! */
    89. OS_CREATETASK(&TCBHP, "HP Task", HPTask, 100, StackHP);
    90. OS_CREATETASK(&TCBLP, "LP Task", LPTask, 50, StackLP);
    91. OS_Start(); /* Start multitasking */
    92. return 0;
    93. }
    Display All



    ...where exactly will be VarA and VarB stored on the stack?

    embOS calls at taskswitch the Save function for the current task and the Restore function for the next task.

    Is this the end of the stack or a fixed place in the beginning of the stack?

    embOS saves the extended task context at the current task stack position.

    Do I need to tell the OS somehow that there is more stack needed for the context extension?

    No, that's not necessary since we use pointer arithmetic for the stack position calculation:
    p = ((CONTEXT_EXTENSION*)pStack) - (1 - OS_STACK_AT_BOTTOM);


    Best regards,
    Til
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.
  • Hi Til,
    which embOS (Compiler, CPU) do you use?
    I use NEC V850 and Greenhills Multi.


    Do I need to tell the OS somehow that there is more stack needed for the context extension?
    No, that's not necessary since we use pointer arithmetic for the stack position calculation:
    p = ((CONTEXT_EXTENSION*)pStack) - (1 - OS_STACK_AT_BOTTOM);
    I understand the pointer calculation, but how can I be sure that this place on the stack will not be overwritten?
    In the example just the next place on the stack which is passed is written but I see no modification of the stackpointer. What happens in case an interrupt occurs just after p->VarA = _VarA; was executed?. As far a I could see in the debugger interrupts are not disabled while save/restore context is executed.
    I just wondered a little that the current stack pointer does not belong to the stack of the current running task (the passed stack pointer was from the active task) :huh:
    I just think that while the context switch is active the system stack is used, am I right?

    My current understanding is the following (please correct me if I am Wrong):
    When the OS wants to make a context switch it starts to save the current task context on the stack of the active task. Than it takes over the control and switches over to system stack as current stack. The saveContext function is called for the current task and gets the position of the last used entry of the task stack. Because this is currently not used any more as active stack it is save to write there without modifying the stack pointer. When this task should be activate again first the OS call the restore function of the task and passed the stack pointer of the task stack which should be activated. Now the data can be recovered and after this the OS recovers the task context.

    Is there a possibility in case an interrupt occurs while a save/restore context is in processing that the OS_LeaveInterrupt at the end of the interrupthandler triggers a contextchange while the current context change is running?

    In my application sometimes the stored data gets corrupted sometimes. When this happens I figured out that my task was interrupted by a context change or an interrupt but at the moment I cannot say this for sure which of them :( .
  • HI,

    the tast stack place will not be overwritten because embOS runs on the system stack (C stack) when the Extended task context Save function is called. All occured interrupts will run on this sytem stack and not on the task stack.

    My current understanding is the following (please correct me if I am Wrong):...

    Yes, that's correct.

    Is there a possibility in case an interrupt occurs while a save/restore context is in processing that the OS_LeaveInterrupt at the end of the interrupthandler triggers a context change while the current context change is running?

    The interrupt routine could trigger a context switch but this context switch would not be executed while the scheduler is running.

    Best regards,
    Til
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.