Interrupting a Spin method
Hello everyone!
I'm working on a motion sim project.
The conception in short is, that Propeller communicates with the PC on serial port, accepts commands, and moves the actuators according to them.
The messages(commands) can be on a variety of levels. There are low level commands, like enabling the bridge drivers. This require a few instructions to be executed. And there are high level commands. Like when a command asks for a specific emulated g vector, and the Propeller acts according to the command and the chassis current state. These can be longer to be executed. (So long that it won't finished when the next command arrives. This is important. Later explained.)
I've a cog that runs the message interpreter, which communicates on the serial port, and calls the needed methods. Lets call this part: interpreter. (Spin routines)
I've more cogs those reads/writes certain parts of the main memory. Reads positions, temperature, motor-current etc, and drive the motors, according to them. Lets call this part: driver. (Assy routines)
I've the control application which methods' are called by the message interpreter. This reads/writes the memory parts that driver uses. Lets call this part: controller. (Spin routines)
And now the problem/question.
At the moment, if controller is busy, executing a call, it can't accept commands. Since interperter calls a method of controller, only can call another if controller method returns.
Controller's methods must be interruptable. But how?
I dont want to write these methods to listen to some flag, to interrupt or not. I want them to be interrupted form the outside.
The most easy way that I can think of, if interpreter launches controller's methods into a new cog. And when it needs to be terminated, it simply stops that cog, and launches the new method (probally into the same cog). This seems to be good for the first sight, but it can be slow.
How long it takes, to init a cog? If I'm right, it takes at least the time that requires to copy the 512 long, so it's around 16*512 clock and some more.
The simulator program sends the new data every 10ms (it's LFS), so for the first blink, stopping and initing a cog on every command seems suboptimal for me.
So, what do you think, is there a clever way to, stop a certain Spin method form outside and start a new one, apart from stop the cog that runs the method, and initing a (new) cog to start the new method?
I'm working on a motion sim project.
The conception in short is, that Propeller communicates with the PC on serial port, accepts commands, and moves the actuators according to them.
The messages(commands) can be on a variety of levels. There are low level commands, like enabling the bridge drivers. This require a few instructions to be executed. And there are high level commands. Like when a command asks for a specific emulated g vector, and the Propeller acts according to the command and the chassis current state. These can be longer to be executed. (So long that it won't finished when the next command arrives. This is important. Later explained.)
I've a cog that runs the message interpreter, which communicates on the serial port, and calls the needed methods. Lets call this part: interpreter. (Spin routines)
I've more cogs those reads/writes certain parts of the main memory. Reads positions, temperature, motor-current etc, and drive the motors, according to them. Lets call this part: driver. (Assy routines)
I've the control application which methods' are called by the message interpreter. This reads/writes the memory parts that driver uses. Lets call this part: controller. (Spin routines)
And now the problem/question.
At the moment, if controller is busy, executing a call, it can't accept commands. Since interperter calls a method of controller, only can call another if controller method returns.
Controller's methods must be interruptable. But how?
I dont want to write these methods to listen to some flag, to interrupt or not. I want them to be interrupted form the outside.
The most easy way that I can think of, if interpreter launches controller's methods into a new cog. And when it needs to be terminated, it simply stops that cog, and launches the new method (probally into the same cog). This seems to be good for the first sight, but it can be slow.
How long it takes, to init a cog? If I'm right, it takes at least the time that requires to copy the 512 long, so it's around 16*512 clock and some more.
The simulator program sends the new data every 10ms (it's LFS), so for the first blink, stopping and initing a cog on every command seems suboptimal for me.
So, what do you think, is there a clever way to, stop a certain Spin method form outside and start a new one, apart from stop the cog that runs the method, and initing a (new) cog to start the new method?
Comments
one possibility ist to run the process, that has to be interruptable as a state machine in loops. Just to kill tasks/cogs will lead to unknown results, I fear.
The time for one loop has to be shorter than the allowed latency time.
I have done something like that using PropBasic (because of speed) for such a job. The PropBasic Cog (2-axis step motor controller) gets its commands from a Spin Cog.
The signal for new commands/parameters can be a hub variable or an output pin.
Best luck,
Christof
Yes, this might be something that I want. And it would allow to stop a spin process without stop the cog, that runs it.
But.
How can we start a new Spin method into that cog again? This is the more important question here. Is there any way to keep a cog with the spin interpreter loaded, and call a method to be executed in that cog from another cog? Or something similar.
We can kill a Spin method with cogstop (and necessary the cog that was running it). We can init a new one with cognew or coginit. But how to get rid the cog's boot up time, every time a spin method launches. This is the question, that could lead to a solution, I think.
This is simplest if you have 1+ cog free. The first step is to lock protect ALL of the shared resources that a parallel interpreter/controller would access. (if the 8 hardware locks are not enough, 1 lock can be used to protect the code that implements an arbitrary number of software locks) The next step is to simply start 2+ copies of the interpreter/controller code.
Lawson