| Author |
Message |
|
|
Posted: Nov 30, 2011 - 08:37 PM |
|

Joined: Nov 30, 2011
Posts: 5
Location: Jalisco, Mexico
|
|
Hello World!! My name is Roberto and i´m new here so i wanted say hi to everybody in this great community.
Also i want to ask for help, the thing is that i´m making a round robin scheduler function but, i don't understand how to handle the stack pointer of the diferent tasks, my PCB is the following:
struct PCB_TYPE
{
unsigned char id; // the proccess id
functype process_ptr; // a pointer to the task
unsigned char status; // the status of the task
int *task_SP; // a poiner to the task´s stack
};
and i´m using this macro to read the context of the cpu
#define SAVE_CONTEXT() \
asm volatile ( \
"push r0 \n\t" \ //saving rx on stack
"push r1 \n\t" \
"push r2 \n\t" \
"push r3 \n\t" \
...
...
...
"push r29 \n\t" \
"push r30 \n\t" \
"push r31 \n\t" \
"in r0, __SREG__ \n\t" \ //save status register in r0
"push r0 \n\t" \ // save the status on stack
);
and the problem is how handle the stack pointer for read it and save it in task_SP, so would be great if someone can explain it to me, thanks for your time
[something a bit sensible added to pointless thread title] |
|
|
| |
|
|
|
|
|
Posted: Nov 30, 2011 - 08:49 PM |
|


Joined: Jun 15, 2008
Posts: 1762
Location: North Carolina USA
|
|
Unless you allocate a separate stack space for each task on a heap you can't just back up the stack pointer to give a time slice to a stack. A function call or interrupt will overwrite stack needed for a suspended task.
Not saying you can't get around this, but you have to give more details about how you are going to accomplish this. |
|
|
| |
|
|
|
|
|
Posted: Nov 30, 2011 - 09:28 PM |
|


Joined: Sep 04, 2002
Posts: 21274
Location: Orlando Florida
|
|
| Also, you can see how a dozen other software engineers wrote their version of an AVR task switcher by looking in the projects section here for RTOS (Real Time Operating System). At least a dozen. |
_________________ Imagecraft compiler user
|
| |
|
|
|
|
|
Posted: Dec 01, 2011 - 04:07 AM |
|


Joined: Apr 20, 2007
Posts: 6089
Location: Long Island New York
|
|
Oh yummy.....SPAM!!
Jim |
_________________ Jim
I have decided that I am no longer going to plan anything in advance. In a court of law this is called Pre-Meditated, and does not look good for the defense.....
Timer function not working properly? Check CLKDIV8 Fuse first
|
| |
|
|
|
|
|
Posted: Dec 01, 2011 - 06:45 AM |
|

Joined: Nov 30, 2011
Posts: 5
Location: Jalisco, Mexico
|
|
thanks for the answers, and you´re right, i´m planing to use a diferent stack for each task, and the reality is that i don´t know how to read the addres of those stacks with asm instructions yet, this is the idea for now:
unsigned char [MAX_TASKS][35]; // one stack for each task
and read the address of every row and save into the stack pointer (at the right time), it´s maybe a bad idea, i´m new on this, so if i´m making it bad, i´ll apreciate any help.
a while, I thought this: what if i make a pointer to a defined address for example the address "100" and in that space i put the real address of the stack i think with asm i can read that address and write the stack pointer register with it, what do you think?
PS i have seen some other codes but still i don´t know how do they handle the context |
|
|
| |
|
|
|
|
|
Posted: Dec 01, 2011 - 12:55 PM |
|


Joined: Jun 15, 2008
Posts: 1762
Location: North Carolina USA
|
|
| 35 bytes will store the registers but you need a lot more to store the entire stack at the time of task interruption. This will be the local storage for each subroutine and return addresses with maybe an interrupt on top of everything else. 8 bit micros don't have the memory to make that useful, in most cases. |
|
|
| |
|
|
|
|
|
Posted: Dec 01, 2011 - 02:12 PM |
|

Joined: Nov 30, 2011
Posts: 5
Location: Jalisco, Mexico
|
|
| i think i just need 35 bytes because, i only need to save 32 registers plus the pc register and the status register, well i´ll grown it to 40 bytes, and i know that 8 bits mcus are weak, but at this moment i just want to learn, it won´t be to run spectacular aplications just i want it works, do you think i need to save more registers than those? |
|
|
| |
|
|
|
|
|
Posted: Dec 02, 2011 - 12:12 AM |
|

Joined: Jul 19, 2011
Posts: 47
Location: Haifa, Israel
|
|
What about local variables of functions? Return addresses?
You know a task switch may happen when you are deep in a nested function call. |
|
|
| |
|
|
|
|
|
Posted: Dec 02, 2011 - 12:17 AM |
|


Joined: Nov 22, 2002
Posts: 12055
Location: Tangent, OR, USA
|
|
How do you deal with a variable that is shared among several tasks?
Jim |
_________________ Jim Wagner
Oregon Research Electronics, Consulting Div.
Tangent, OR, USA
"The only thing standing between us and victory is defeat" P.G.Wodhouse in Wooster & Jeeves series
|
| |
|
|
|
|
|
Posted: Dec 02, 2011 - 02:07 AM |
|


Joined: Nov 11, 2003
Posts: 3904
Location: Chicago Illinois USA
|
|
Back in the DOS days, TopSpeed Modula had a rather brain-damaged thread system. You could only start a thread 63 times: The 64th time, you program dumped. Once started, a thread could not stop, or your program dumped. Once started, you couldn't get the number back...
So here's what I did.
In a procedure call, the compiler assumed all the registers would be toast on return, so I didn't have to preserve them. I used a scrap of assembly to save the stack pointer, fetch another from the linked-list of runnable tasks, and do a return. Poof, a context switch on request.
Interrupts didn't do context switches, but the interrupt routine could manipulate the list of runnable processes, so it just set a flag or perhaps added the task that was waiting for it back into the list so it would go again.
To start a new thread, I just allocated some memory for the stack from heap put the address I wanted it to "return" to at the top, put the new "Stack Pointer" into the list of runnable tasks.
Since I figured without an IO event, there wasn't any point in tasking, so if the foreground task was waiting for a keystroke, it just took itself out of the list and called the switch procedure. The keyboard interrupt called the normal dos keyboard vector, then put the foreground process back into the ready list.
Since it wasn't preemptive, I didn't have to worry about global variables and the like. You could kill a task by taking it out of the ready list and deallocating its stack. A task could even kill itself.
The result was pretty impressive. On any "Screen" where it would take a while to sum up a bunch of records or something, it would give the user control, and the sum fields would count away. If they closed the screen before it finished, no problem, the procedure that showed the screen allocated and started the task, it just killed the task and deallocated the stack. Impressed programmers, but users thought that was how it was supposed to work. |
_________________ Discursive design,
Torby
Some days, it's just not worth chewing through the restraints.
|
| |
|
|
|
|
|
Posted: Dec 04, 2011 - 08:43 AM |
|

Joined: Nov 30, 2011
Posts: 5
Location: Jalisco, Mexico
|
|
thanks to all for your time and for help me, i read for my doub and the point is that i did not explain myself, the most big problem was that i didn´t know how to mix variables in c, with asm code, i´m just an ignorant novice, but i´m here to change that, now the problem is that compiler doesn´t recognize the following asm instruction
asm volatile( \
"push r0 \n\t" \
"push r1 \n\t" \
...
...
"in r16 , SREG \n\t");
it shows me "error constant value required" file:cc0Peyo.s
i know the problem is the last instruction because is i put it like comment, the compiler build the proyect
do you can explain me why? i´m using avrstudio 5
and, I had increased the stack for each task it to 60 Bytes i think is enough for the tasks that the mcu going to run, i´m doing this to get the basics skills, so for this proyect, the mcu won´t make anything extraordinary, maybe it´ll control an alphanumerical LCD module and a rotabit or something easy like those things, the objetive it´s make it work |
Last edited by alt0174 on Dec 04, 2011 - 09:13 AM; edited 1 time in total
|
| |
|
|
|
|
|
Posted: Dec 04, 2011 - 08:53 AM |
|

Joined: Jun 25, 2001
Posts: 348
Location: Melbourne Australia
|
|
| What compiler are you using ? |
|
|
| |
|
|
|
|
|
Posted: Dec 04, 2011 - 09:15 AM |
|

Joined: Nov 30, 2011
Posts: 5
Location: Jalisco, Mexico
|
|
|
|
|
|
|
Posted: Dec 04, 2011 - 10:20 AM |
|


Joined: Mar 27, 2002
Posts: 18599
Location: Lund, Sweden
|
|
Your task now is to create the smallest possible program that displays the problem. Since this is "inline assembler" producing a compilation error this should not be hard (i.e. should taker a couple of minutes or so). Then publish that minimal demonstrator here.
It just might be that you discover the problem yourself while creating this minimal demonstrator. If so, you have exercised one common fault-seeking technique - "Reduction of the problem space" - to a successful end. |
|
|
| |
|
|
|
|
|
Posted: Dec 04, 2011 - 11:01 AM |
|


Joined: Jul 23, 2001
Posts: 2440
Location: Osnabrueck, Germany
|
|
|
Quote:
"in r16 , SREG \n\t");
it shows me "error constant value required" file:cc0Peyo.s
i know the problem is the last instruction because is i put it like comment, the compiler build the proyect
do you can explain me why?
The SREG is part of a string, therefore it is not replaced by the preprocessor. You have to pass in such things as operand.
http://www.nongnu.org/avr-libc/user-man ... e_asm.html |
_________________ Stefan Ernst
|
| |
|
|
|
|
|
Posted: Dec 04, 2011 - 02:11 PM |
|


Joined: Dec 21, 2006
Posts: 1488
Location: Saar-Lor-Lux
|
|
|
alt0174 wrote:
Code:
asm volatile( \
"push r0 \n\t" \
"push r1 \n\t" \
...
...
"in r16 , SREG \n\t");
Write
Code:
"in r16, __SREG__"
I don't think you'll have much fun with inline assembler for such a task.
This is not a generic C question, it's specific to avr-gcc. |
|
|
| |
|
|
|
|
|
Posted: Dec 04, 2011 - 04:27 PM |
|


Joined: Jul 18, 2005
Posts: 62371
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
|
|
|
|
|