Friday, August 1st 2014, 3:41am UTC+2

You are not logged in.

  • Login
  • Register

Dear visitor, welcome to SEGGER Forum. If this is your first visit here, please read the Help. It explains how this page works. You must be registered before you can use all the page's features. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

sowiso

Beginner

Date of registration: Oct 19th 2011

Posts: 2

1

Wednesday, October 19th 2011, 4:08pm

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
typedef struct {
	OS_U32 VarA;
	OS_U32 VarB;
} T_context_extention;

...

OS_U32 _VarA;
OS_U32 _VarB;

...

static void _SaveConext(void * pStack)
{
	T_context_extention* p;
	p =((T_context_extention*)pStack) - (1 - OS_STACK_AT_BOTTOM); /* create pointer */
	/* save all members of ther structure */
	p->VarA = _VarA;
	p->VarB = _VarB;
}

static void _RestoreContext(const void * pStack)
{
	T_context_extention* p;
	p =((T_context_extention*)pStack) - (1 - OS_STACK_AT_BOTTOM); /* creat pointer */
	/* save all members of ther structure */
	_VarA = p->VarA;
	_VarB = p->VarB;   
}


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

SEGGER - Til

Super Moderator

Date of registration: Nov 14th 2007

Posts: 201

2

Thursday, October 20th 2011, 3:12pm

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/C++ Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "RTOS.h"

OS_STACKPTR int StackHP[128], StackLP[128];          /* Task stacks */
OS_TASK TCBHP, TCBLP;                        /* Task-control-blocks */

OS_U32 _VarA;
OS_U32 _VarB;

/*********************************************************************
*
*       _Restore
*       _Save
*
*  Function description
*    This function pair saves and restores an extended task context.
*    In this case, the extended task context consists of just a single
*    member, which is a global variable.
*/

typedef struct {
  OS_U32 VarA;
  OS_U32 VarB;
} CONTEXT_EXTENSION;

static void _Save(void * pStack) {
  CONTEXT_EXTENSION * p;
  p = ((CONTEXT_EXTENSION*)pStack) - (1 - OS_STACK_AT_BOTTOM);          // Create pointer to our structure
  //
  // Save all members of the structure
  //
  p->VarA = _VarA;
  p->VarB = _VarB;

}

static void _Restore(const void * pStack) {
  const CONTEXT_EXTENSION * p;
  p = ((const CONTEXT_EXTENSION *)pStack) - (1 - OS_STACK_AT_BOTTOM);   // Create pointer to our structure
  //
  // Restore all members of the structure
  //
  _VarA = p->VarA;
  _VarB = p->VarB;
}

/*********************************************************************
*
*       Global variable which holds the function pointers
*       to save and restore the task context.
*/
const OS_EXTEND_TASK_CONTEXT _SaveRestore = {
  _Save,
  _Restore
};

/********************************************************************/


/*********************************************************************
*
*       HPTask
*
*  Function description
*    During the execution of this function, the thread-specific
*    global variable has always the same value of 1.
*/
static void HPTask(void) {
  OS_ExtendTaskContext(&_SaveRestore);
  _VarA = 1;
  _VarB = 2;
  while (1) {
    OS_Delay (10);
  }
}

/*********************************************************************
*
*       LPTask
*
*  Function description
*    During the execution of this function, the thread-specific
*    global variable has always the same value of 2.
*/
static void LPTask(void) {
  OS_ExtendTaskContext(&_SaveRestore);
  _VarA = 3;
  _VarB = 4;
  while (1) {
    OS_Delay (50);
  }
}

/*********************************************************************
*
*       main
*/
int main(void) {
  OS_IncDI();                      /* Initially disable interrupts  */
  OS_InitKern();                   /* Initialize OS                 */
  OS_InitHW();                     /* Initialize Hardware for OS    */
  /* You need to create at least one task here !                    */
  OS_CREATETASK(&TCBHP, "HP Task", HPTask, 100, StackHP);
  OS_CREATETASK(&TCBLP, "LP Task", LPTask,  50, StackLP);
  OS_Start();                      /* Start multitasking            */
  return 0;
}



Quoted

...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.

Quoted

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.

Quoted

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

sowiso

Beginner

Date of registration: Oct 19th 2011

Posts: 2

3

Thursday, October 20th 2011, 4:10pm

Hi Til,

Quoted

which embOS (Compiler, CPU) do you use?
I use NEC V850 and Greenhills Multi.


Quoted

Quoted

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 :( .

SEGGER - Til

Super Moderator

Date of registration: Nov 14th 2007

Posts: 201

4

Thursday, October 20th 2011, 6:04pm

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.

Quoted

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

Yes, that's correct.

Quoted

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