\ ********************************************************************* \ * \ Filename: task.txt * \ Date: 18.09.2011 * \ FF Version: 3.8 * \ 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 36 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. \ The end of TIB is used as the HOLD area. When numeric output is \ used, the tibsize should be at least 10. \ QUIT accepts tibsize-10 characters. \ \ uareasize = 36 + 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 ram here flash + , \ User pointer ts ss rs as bs 4 for over c, + next cell+ \ Task size ram allot \ The user area is in ram ; \ 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 ul@ 0= \ Already running if \ Pointer to task area dup 2- task ! \ save area = uarea+cell+addsize c@+ up@ + cell+ !p>r \ a t+3 \ s0 = rsave + ssize - 1 c@+ @p + 1- dup s0 ! \ a t+4 p! p2+ \ s0 to save area p2+ \ dummy P to save area \ tib = rsave + rsize c@ s0 @ + 1+ tiu ! \ a p! p2+ \ taskloop-addr to save area 1 pc! \ return stack size to save area @p up@ ! \ end of save area to restore pointer 0 ul! \ no link yet r>p else 2drop then op! \ run the operator task ; \ Insert a new task after operator in the linked list. \ May only be executed from the operator task \ task-addr -- : run @ up! ul@ 0= \ Already running if up@ \ task-uarea op! ul@ \ task-uarea operator-ulink over ul! swap up! ul! then busy \ mark the task as busy 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 idle \ mark the task as idle 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 idle \ mark the task as idle up! \ and move to next user area repeat 0 ul! op! then ; \ List all running tasks : tasks ( -- ) up@ op! begin up@ task @ 6 - c>n op! .id space up! ul@ op@ - while ul@ up! repeat up! ; hex ram