\ ********************************************************************* \ * \ Filename: task.fth * \ Date: 15.1.2008 * \ FF Version: 3.2 * \ Copyright: Mikael Nordman * \ Author: Mikael Nordman * \ ********************************************************************* \ FlashForth is licensed acording to the GNU General Public License* \ ********************************************************************* \ TASK leaves the userarea address on the stack. \ The basic size of a task is decimal 26 bytes. \ The return stack, the parameter stack and the tib buffer areas \ are in addition to that. \ These are allocated at the end (high address) of the user area. \ Own user varibles can be allocated from offset 2 upwards, \ below the return stack. Addsize must reflect any additonal \ user variables that are used. \ uareasize = 26 + rsize + tibsize + ssize + addsize \ \ The operator task is predefined. \ flash decimal 72 62 96 0 task operator \ \ A background task with a 12 cell return stack and a \ 12 cell parameter stack and no tib. \ flash decimal 0 24 24 0 task bg1 \ \ A background task with also one extra user variable. \ flash decimal 0 24 24 2 task bg2 \ ram decimal 2 user bg2_cnt \ Do not use user variables as task specific variables \ User variables are needed by _words_common_to_several_tasks_ \ which need some task specific data storage. -task marker -task hex ram \ Near definition saves memory ! : up! up ! ; : up@ up @ ; : op@ operator @ ; : ul@ ulink @ ; : ul! ulink ! ; : op! op@ up! ; \ access user variables of other task : his ( task-addr var-addr -- addr ) up@ - swap @ + ; \ Define a new task \ A new task must be defined in the flash memory space : task ( tibsize stacksize rsize addsize -- ) flash create up@ s0 - dup \ Basic size ts ss rs as bs bs rhere + , \ User pointer ts ss rs as bs 4 for over , + next cell+ \ Task size ram allot ; \ Initialise a user area and link it to the task loop \ May only be executed from the operator task : tinit ( taskloop-addr task-addr -- ) \ use task user area @+ up! \ a t+2 \ rsave = uarea+cell+addsize @+ up@ + cell+ dup rsave ! \ a t+4 rbuf \ Make space for one return adress on the stack 1+ up@ ! 1 rcnt ! \ a t+4 \ s0 = ssave = rsave + ssize - 1 @+ rsave @ + 1- dup s0 ! ssave ! \ a t+6 \ tib = rsave + rsize @ s0 @ + 1+ tib ! \ a \ taskloop-addr to return stack rsave @ ! 0 ul! 0 state ! op! \ run the operator task ; \ Insert a new task after operator in the linked list. \ May only be executed from the operator task : run ( task-addr -- ) @ up! ul@ 0= \ Already running ? if up@ \ task-uarea op! ul@ \ task-uarea operator-ulink over ul! swap up! ul! then op! \ run operator task ; \ End a task by linking it out from the linked list \ May only be executed from the operator task : end ( task-addr -- ) @ up! ul@ if up@ op! begin \ find the uarea in the linked list dup ul@ <> \ uarea flag while ul@ up! \ uarea repeat up@ \ uarea prev-uarea swap up! \ prev-uarea ul@ \ prev-uarea next-uarea 0 ul! \ ulink of a ended task is zero swap up! \ next-uarea ul! \ then op! ; \ End all tasks except the operator task \ May only be executed from the operator task : single ( -- ) ul@ op@ <> \ Are there any running tasks ? if ul@ op@ ul! \ link operator to himself up! \ move to next user area begin ul@ op@ <> \ is this the last linked user area ? while ul@ 0 ul! \ write zero to ulink up! \ and move to next user area repeat 0 ul! op! then ; hex ram