Hello Erich,

My original 2019 problem of "why can't I redirect emit to output to my
LCD from a task" is perhaps most simply addressed by an addition to the
documentation. Once (I) it is understood that the user area a task has
access to needs to be explicitly populated, it all works as expected.
Your solutions would cover such a documentation addition I think.

> There is an area in EEPROM holding all these values.
> Much to my surprise these values are stored at some odd location. Look
> for "EE_INITUSER:" in main.lst (the assembler list file). It will
> reveal this location:
> > |                  ; default user area
> > |                  EE_INITUSER:
> > | 000074 00 00         .dw 0  ; USER_STATE
> > | 000076 00 00         .dw 0  ; USER_FOLLOWER
> > | 000078 ff 10         .dw rstackstart  ; USER_RP
> In this case $74. So we can pick things from $74 plus some offset.
>
> If I want to do this in run-demo, then a Forth constant holding that
> offset would be nice (change to AmForth asm).

I think such a Forth constant would be a good addition, and gives the
option of ee>ram in a custom task-init.

> Making the HOLD area (and possibly TerminalInputBuffer) task local,
> can be solved, no doubt. But I'm not convinced that this is the way to
> go unless different tasks operate on separate output destinations.

Making the various buffers (HLD, PAD, etc.) task local appeals to me,
but (I think) it would mean changes rather than additions to AmForth
and the "one resource" issue would always remain.
       
> Now back to your original problem. I rephrase: "Wouldn't it be
> nice if I have one or more background tasks running along and
> printing their output as they go --- independantly of each
> other"?

In mitigation, each of my outputing tasks did have its own output device :)

> My experiments reminded me very clearly, that more than one task
> emitting output on the same destination can only be a bad idea.

Agreed.

Best wishes,
Tristan

On 06May20 20:33, Erich Wälde wrote:
> 
> Hello Tristan,
> 
> back to mulitasking on AmForth.
> 
> I spend an afternoon to create a background task, which does some
> output by itself (see code below). There is nothing really new in
> this. If I equip the background tasks with base and pointers to emit
> (and emit?), it does work, including pictured output of numbers. 
> 
> I gained a few insights along the way:
> 
> 1.
> the background task has any form I want. So noone can stop me from
> writing 
> > | : run-demo
> > |   \ some init stuff
> > |   #10 base !
> > |   \ loop
> > |   begin
> > |     \ repeated work goes here
> > |   again
> > | ;
> This "init" space can be used to set missing bits without any need to
> change init-task.
> 
> 2.
> however: the real XT found in emit is hidden behind a defer.
> > | ' emit defer@
> will not work in run-demo. 
> 
> First solution: store this value in a constant before defining
> run-demo.
> 
> > | ' emit defer@ constant emit.orig
> > | 
> > | : run-demo
> > |   emit.orig is emit
> > |   ...
> > | ;
> 
> This works for the io functions emit emit? key key?. I expect this to
> work for the prompts .ok .ready .error .input as well.
> 
> But storing these values separately seems kind of odd.
> 
> Second solution: There is an area in EEPROM holding all these values.
> Much to my surprise these values are stored at some odd location. Look
> for "EE_INITUSER:" in main.lst (the assembler list file). It will
> reveal this location:
> > |                  ; default user area
> > |                  EE_INITUSER:
> > | 000074 00 00         .dw 0  ; USER_STATE
> > | 000076 00 00         .dw 0  ; USER_FOLLOWER
> > | 000078 ff 10         .dw rstackstart  ; USER_RP
> In this case $74. So we can pick things from $74 plus some offset.
> 
> If I want to do this in run-demo, then a Forth constant holding that
> offset would be nice (change to AmForth asm).
> 
> Third solution (not tested) instead of 
> > | : task-init ( tib -- )
> > |   dup tib>tcb over tib>size  0 fill \ clear RAM for tcb and stacks
> > |   ...
> we could write something like
> > | : task-init ( tib -- )
> > |   dup tib>tcb over tib>size  \ -- r-addr length
> > |   ee_user rot rot            \ -- e-addr r-addr length
> > |   \ possibly 2/ to correct for cells
> > |   ee>ram
> > |   ...
> instead. So we get all the missing stuff delivered. This needs the
> same Forth constant as in 2.
> 
> I expect this to break on targets other than avr8 --- at least for my
> current lack of understanding, how/where this information is stored on
> the other platforms.
> 
> 
> Still reading? No, I have not even tried to go beyond what we did know
> already. 
> 
> 
> However.
> 
> I wrote:
> > Now back to your original problem. I rephrase: "Wouldn't it be
> > nice if I have one or more background tasks running along and
> > printing their output as they go --- independantly of each
> > other"?
> 
> My experiments reminded me very clearly, that more than one task
> emitting output on the same destination can only be a bad idea. In the
> end you get garbled output. Unless of course, you lock access to this
> one resource using semaphores. Thats one more thing to work out.
> 
> "this one resource" starts pointing to a better understanding. This is
> the classical "several clients/tasks compete for a single resource"
> problem. This is what an operating system kernel must organize all the
> time. Any access to (any) resource must go through one instance.
> 
> So we enter the world of locks and queues and privileges and
> priorities and what not.
> 
> Use case:
> 
> Task-1 acquires the "output on uart0"-lock.
> { Task-1 prepares the output
>   Task-1 emits the output } possibly more than once
> Task-1 releases the lock.
> 
> This also includes the fact, that emitting e.g. on uart, takes long.
> You copy one byte to the output register, and then basically you call
> pause. A task switch occurs at this point. Probably several task
> switches later, the next byte can be emitted. For some applications
> this might work. For other maybe not. 
> 
> Making the HOLD area (and possibly TerminalInputBuffer) task local,
> can be solved, no doubt. But I'm not convinced that this is the way to
> go unless different tasks operate on separate output destinations.
> 
> Having cooperative multitasking basically offers that one task holds
> the cpu and calls pause only after it is done. But you need to check
> carefully, that pause isn't called in unexpected places.
> 
> Having one task to emit output, and all the other report to this one?
> Enter the world of queues, dynamic memory allocation and locks. :-/
> 
> 
> Well well. I hate to say that, but this seems like a slippery slope.
> And no, I'm neither a good system programmer nor living in kernel
> space. So my understanding of this sort of problems is very limited.
> 
> I want to see if semaphores can help in some cases.
> 
> 
> One more thing: in my rs485-bus project, I hit a similar problem, of
> course: several sensor stations sending their values whenever their
> local clock says "it's time", to the one resource called rs485 bus. No
> thanks. My solution thus far is: The bus master is soliciting data
> from each station, when the bus master's clock says "it's time". And I
> have spend some effort to silence the sensor stations, whenever they
> start, and even if they receive a command they do not understand. This
> stringent system runs since 2011, with very few problems (I get
> a hickup once in a while, but I have not change code in a long time).
> 
> 
> So much for today.
> 
> Cheers,
> Erich
> 
> 
> --- code example ---
> \ 2020-05-06
> \ try to make multitasker play tristans game.
> 
> \ --- loaded by " make marker "
> \ include lib/builds.frt
> \ include lib/forth2012/core/erase.frt
> \ include lib/dot-base.frt
> \ include lib-avr8/imove.frt
> \ include lib-avr8/bitnames.frt
> \ include lib-avr8/forth2012/core-ext/marker.frt
> \ include lib-avr8/forth2012/core/environment-q.frt
> \ include lib-avr8/dot-res.frt
> \ include lib-avr8/forth2012/core/avr-values.frt
> \ include lib/forth2012/core/is.frt
> \ include lib/forth2012/tools/dumper.frt
> \ include lib-avr8/hardware/interrupts.frt             ???
> \ include atmega644p.fs
> \ include first.fs
> 
> marker --start--
> 
> \ --- leds are on PorbB 0,1,2,3 ---
> PORTB 2 portpin: led.0
> PORTB 3 portpin: led.1  
> PORTB 4 portpin: led.2  
> PORTA 7 portpin: led.3
> 
> 
> \ --- famous includes ---
> : ms        ( n -- )     0 ?do pause 1ms loop ;
> : u0.r      ( u n -- )   >r 0 <# r> 0 ?do # loop #> type ;
> 
> include leds.fs
> 
> ' emit defer@ constant emit.orig
> 
> $74 constant ee_user \ EE_INITUSER, looked up in mail.lst
> #14 constant ee_emit \ offset into user area
> #16 constant ee_emitq
> 
> \ --- include multitasker ---
> include lib/multitask.frt
> variable N
> 
> : run-demo
>   \ --- task 2 ---
>   #7 base ! \ funny base to identify output.
>   \ emit.orig is emit
>   ee_user ee_emit  + @e is emit
>   ee_user ee_emitq + @e is emit?
>   [char] t emit cr
>   led.3 on
>   begin
>     1 N +!
>     led.2 on
>     #250 ms
>     led.2 off
>     [char] . emit space N @ . cr
>     #250 ms
>   again
> ;
> $40 $40 0 task: task_demo
> \ create task, allot tcb + stack space
> : start-demo
>   task_demo tib>tcb activate
>   \ words after this line are run in new task
>   run-demo
> ;
> : starttasker
>   task_demo task-init
>   \ create TCB in RAM
>   start-demo
>   \ activate tasks job
>   onlytask
> \ task_demo tcb>tid alsotask \ error
>   task_demo tib>tcb alsotask
>   multi
> ;
> 
> 
> 
> : init
>   42 N !
>   +leds leds-intro
>   cr [char] i emit space N ?
>   cr
> ;
> : run-turnkey
>   \ make cmd loop task-1
>   \ start task-2
>   \ activate multitaskingMultitasking
>   applturnkey
>   init
>   starttasker
> ;
> 
> 
> 
> 
> -- 
> May the Forth be with you ...
> 
> 
> _______________________________________________
> Amforth-devel mailing list for http://amforth.sf.net/
> Amforth-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/amforth-devel
> 


_______________________________________________
Amforth-devel mailing list for http://amforth.sf.net/
Amforth-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amforth-devel

Reply via email to